progress when saving state (JAL-870) and hack to trap possible gui race condition...
[jalview.git] / src / jalview / gui / Desktop.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.gui;
19
20 import jalview.bin.Cache;
21 import jalview.io.*;
22 import jalview.ws.params.ParamManager;
23
24 import java.awt.*;
25 import java.awt.datatransfer.*;
26 import java.awt.dnd.*;
27 import java.awt.event.*;
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
30 import java.beans.PropertyVetoException;
31 import java.io.BufferedInputStream;
32 import java.io.BufferedOutputStream;
33 import java.io.File;
34 import java.io.FileOutputStream;
35 import java.io.InputStream;
36 import java.lang.reflect.Constructor;
37 import java.net.URL;
38 import java.net.URLConnection;
39 import java.nio.channels.ReadableByteChannel;
40 import java.util.*;
41
42 import javax.swing.*;
43 import javax.swing.event.MenuEvent;
44 import javax.swing.event.MenuListener;
45
46 /**
47  * Jalview Desktop
48  * 
49  * 
50  * @author $author$
51  * @version $Revision: 1.155 $
52  */
53 public class Desktop extends jalview.jbgui.GDesktop implements
54         DropTargetListener, ClipboardOwner, IProgressIndicator, jalview.api.StructureSelectionManagerProvider
55 {
56
57   private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
58
59   /**
60    * @param listener
61    * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
62    */
63   public void addJalviewPropertyChangeListener(
64           PropertyChangeListener listener)
65   {
66     changeSupport.addJalviewPropertyChangeListener(listener);
67   }
68
69   /**
70    * @param propertyName
71    * @param listener
72    * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
73    *      java.beans.PropertyChangeListener)
74    */
75   public void addJalviewPropertyChangeListener(String propertyName,
76           PropertyChangeListener listener)
77   {
78     changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
79   }
80
81   /**
82    * @param propertyName
83    * @param listener
84    * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
85    *      java.beans.PropertyChangeListener)
86    */
87   public void removeJalviewPropertyChangeListener(String propertyName,
88           PropertyChangeListener listener)
89   {
90     changeSupport.removeJalviewPropertyChangeListener(propertyName,
91             listener);
92   }
93
94   /** Singleton Desktop instance */
95   public static Desktop instance;
96
97   public static MyDesktopPane desktop;
98
99   static int openFrameCount = 0;
100
101   static final int xOffset = 30;
102
103   static final int yOffset = 30;
104
105   public static jalview.ws.jws1.Discoverer discoverer;
106
107   public static Object[] jalviewClipboard;
108
109   public static boolean internalCopy = false;
110
111   static int fileLoadingCount = 0;
112
113   class MyDesktopManager implements DesktopManager
114   {
115
116     private DesktopManager delegate;
117
118     public MyDesktopManager(DesktopManager delegate)
119     {
120       this.delegate = delegate;
121     }
122
123     public void activateFrame(JInternalFrame f)
124     {
125       try
126       {
127         delegate.activateFrame(f);
128       } catch (NullPointerException npe)
129       {
130         Point p = getMousePosition();
131         instance.showPasteMenu(p.x, p.y);
132       }
133     }
134
135     public void beginDraggingFrame(JComponent f)
136     {
137       delegate.beginDraggingFrame(f);
138     }
139
140     public void beginResizingFrame(JComponent f, int direction)
141     {
142       delegate.beginResizingFrame(f, direction);
143     }
144
145     public void closeFrame(JInternalFrame f)
146     {
147       delegate.closeFrame(f);
148     }
149
150     public void deactivateFrame(JInternalFrame f)
151     {
152       delegate.deactivateFrame(f);
153     }
154
155     public void deiconifyFrame(JInternalFrame f)
156     {
157       delegate.deiconifyFrame(f);
158     }
159
160     public void dragFrame(JComponent f, int newX, int newY)
161     {
162       delegate.dragFrame(f, newX, newY);
163     }
164
165     public void endDraggingFrame(JComponent f)
166     {
167       delegate.endDraggingFrame(f);
168     }
169
170     public void endResizingFrame(JComponent f)
171     {
172       delegate.endResizingFrame(f);
173     }
174
175     public void iconifyFrame(JInternalFrame f)
176     {
177       delegate.iconifyFrame(f);
178     }
179
180     public void maximizeFrame(JInternalFrame f)
181     {
182       delegate.maximizeFrame(f);
183     }
184
185     public void minimizeFrame(JInternalFrame f)
186     {
187       delegate.minimizeFrame(f);
188     }
189
190     public void openFrame(JInternalFrame f)
191     {
192       delegate.openFrame(f);
193     }
194
195     public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
196             int newHeight)
197     {
198       delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
199     }
200
201     public void setBoundsForFrame(JComponent f, int newX, int newY,
202             int newWidth, int newHeight)
203     {
204       delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
205     }
206
207     // All other methods, simply delegate
208
209   }
210
211   /**
212    * Creates a new Desktop object.
213    */
214   public Desktop()
215   {
216     /**
217      * A note to implementors. It is ESSENTIAL that any activities that might
218      * block are spawned off as threads rather than waited for during this
219      * constructor.
220      */
221     instance = this;
222     doVamsasClientCheck();
223     doGroovyCheck();
224
225     setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
226     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
227     boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
228             false);
229     boolean showjconsole = jalview.bin.Cache.getDefault(
230             "SHOW_JAVA_CONSOLE", false);
231     desktop = new MyDesktopPane(selmemusage);
232     showMemusage.setSelected(selmemusage);
233     desktop.setBackground(Color.white);
234     getContentPane().setLayout(new BorderLayout());
235     // alternate config - have scrollbars - see notes in JAL-153
236     //JScrollPane sp = new JScrollPane();
237     //sp.getViewport().setView(desktop);
238     //getContentPane().add(sp, BorderLayout.CENTER);
239     getContentPane().add(desktop, BorderLayout.CENTER);
240       desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
241       
242     // This line prevents Windows Look&Feel resizing all new windows to maximum
243     // if previous window was maximised
244     desktop.setDesktopManager(new MyDesktopManager(
245             new DefaultDesktopManager()));
246     Rectangle dims = getLastKnownDimensions("");
247     if (dims != null)
248     {
249       setBounds(dims);
250     }
251     else
252     {
253       Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
254       setBounds((int) (screenSize.width - 900) / 2,
255               (int) (screenSize.height - 650) / 2, 900, 650);
256     }
257     jconsole = new Console(this, showjconsole);
258     // add essential build information
259     jconsole.setHeader("Jalview Desktop "
260             + jalview.bin.Cache.getProperty("VERSION") + "\n"
261             + "Build Date: "
262             + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
263             + "Java version: " + System.getProperty("java.version") + "\n"
264             + System.getProperty("os.arch") + " "
265             + System.getProperty("os.name") + " "
266             + System.getProperty("os.version"));
267
268     showConsole(showjconsole);
269
270     this.addWindowListener(new WindowAdapter()
271     {
272       public void windowClosing(WindowEvent evt)
273       {
274         quit();
275       }
276     });
277
278     this.addMouseListener(new MouseAdapter()
279     {
280       public void mousePressed(MouseEvent evt)
281       {
282         if (SwingUtilities.isRightMouseButton(evt))
283         {
284           showPasteMenu(evt.getX(), evt.getY());
285         }
286       }
287     });
288
289     this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
290     // Spawn a thread that shows the splashscreen
291     SwingUtilities.invokeLater(new Runnable()
292     {
293       public void run()
294       {
295         new SplashScreen();
296       }
297     });
298
299     // displayed.
300     // Thread off a new instance of the file chooser - this reduces the time it
301     // takes to open it later on.
302     new Thread(new Runnable()
303     {
304       public void run()
305       {
306         Cache.log.debug("Filechooser init thread started.");
307         JalviewFileChooser chooser = new JalviewFileChooser(
308                 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
309                 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
310                 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
311                 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
312         Cache.log.debug("Filechooser init thread finished.");
313       }
314     }).start();
315     // Add the service change listener
316     changeSupport.addJalviewPropertyChangeListener("services",
317             new PropertyChangeListener()
318             {
319
320               @Override
321               public void propertyChange(PropertyChangeEvent evt)
322               {
323                 Cache.log.debug("Firing service changed event for "
324                         + evt.getNewValue());
325                 JalviewServicesChanged(evt);
326               }
327
328             });
329   }
330
331   /**
332    * recover the last known dimensions for a jalview window
333    * 
334    * @param windowName
335    *          - empty string is desktop, all other windows have unique prefix
336    * @return null or last known dimensions scaled to current geometry (if last
337    *         window geom was known)
338    */
339   Rectangle getLastKnownDimensions(String windowName)
340   {
341     // TODO: lock aspect ratio for scaling desktop Bug #0058199
342     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
343     String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
344     String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
345     String width = jalview.bin.Cache.getProperty(windowName
346             + "SCREEN_WIDTH");
347     String height = jalview.bin.Cache.getProperty(windowName
348             + "SCREEN_HEIGHT");
349     if ((x != null) && (y != null) && (width != null) && (height != null))
350     {
351       int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
352               .parseInt(width), ih = Integer.parseInt(height);
353       if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
354       {
355         // attempt #1 - try to cope with change in screen geometry - this
356         // version doesn't preserve original jv aspect ratio.
357         // take ratio of current screen size vs original screen size.
358         double sw = ((1f * screenSize.width) / (1f * Integer
359                 .parseInt(jalview.bin.Cache
360                         .getProperty("SCREENGEOMETRY_WIDTH"))));
361         double sh = ((1f * screenSize.height) / (1f * Integer
362                 .parseInt(jalview.bin.Cache
363                         .getProperty("SCREENGEOMETRY_HEIGHT"))));
364         // rescale the bounds depending upon the current screen geometry.
365         ix = (int) (ix * sw);
366         iw = (int) (iw * sw);
367         iy = (int) (iy * sh);
368         ih = (int) (ih * sh);
369         while (ix >= screenSize.width)
370         {
371           jalview.bin.Cache.log
372                   .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
373           ix -= screenSize.width;
374         }
375         while (iy >= screenSize.height)
376         {
377           jalview.bin.Cache.log
378                   .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
379           iy -= screenSize.height;
380         }
381         jalview.bin.Cache.log.debug("Got last known dimensions for "
382                 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
383                 + " height:" + ih);
384       }
385       // return dimensions for new instance
386       return new Rectangle(ix, iy, iw, ih);
387     }
388     return null;
389   }
390
391   private void doVamsasClientCheck()
392   {
393     if (jalview.bin.Cache.vamsasJarsPresent())
394     {
395       setupVamsasDisconnectedGui();
396       VamsasMenu.setVisible(true);
397       final Desktop us = this;
398       VamsasMenu.addMenuListener(new MenuListener()
399       {
400         // this listener remembers when the menu was first selected, and
401         // doesn't rebuild the session list until it has been cleared and
402         // reselected again.
403         boolean refresh = true;
404
405         public void menuCanceled(MenuEvent e)
406         {
407           refresh = true;
408         }
409
410         public void menuDeselected(MenuEvent e)
411         {
412           refresh = true;
413         }
414
415         public void menuSelected(MenuEvent e)
416         {
417           if (refresh)
418           {
419             us.buildVamsasStMenu();
420             refresh = false;
421           }
422         }
423       });
424       vamsasStart.setVisible(true);
425     }
426   }
427
428   void showPasteMenu(int x, int y)
429   {
430     JPopupMenu popup = new JPopupMenu();
431     JMenuItem item = new JMenuItem("Paste To New Window");
432     item.addActionListener(new ActionListener()
433     {
434       public void actionPerformed(ActionEvent evt)
435       {
436         paste();
437       }
438     });
439
440     popup.add(item);
441     popup.show(this, x, y);
442   }
443
444   public void paste()
445   {
446     try
447     {
448       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
449       Transferable contents = c.getContents(this);
450
451       if (contents != null)
452       {
453         String file = (String) contents
454                 .getTransferData(DataFlavor.stringFlavor);
455
456         String format = new IdentifyFile().Identify(file,
457                 FormatAdapter.PASTE);
458
459         new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
460
461       }
462     } catch (Exception ex)
463     {
464       System.out
465               .println("Unable to paste alignment from system clipboard:\n"
466                       + ex);
467     }
468   }
469
470   /**
471    * Adds and opens the given frame to the desktop
472    * 
473    * @param frame
474    *          DOCUMENT ME!
475    * @param title
476    *          DOCUMENT ME!
477    * @param w
478    *          DOCUMENT ME!
479    * @param h
480    *          DOCUMENT ME!
481    */
482   public static synchronized void addInternalFrame(
483           final JInternalFrame frame, String title, int w, int h)
484   {
485     addInternalFrame(frame, title, w, h, true);
486   }
487
488   /**
489    * DOCUMENT ME!
490    * 
491    * @param frame
492    *          DOCUMENT ME!
493    * @param title
494    *          DOCUMENT ME!
495    * @param w
496    *          DOCUMENT ME!
497    * @param h
498    *          DOCUMENT ME!
499    * @param resizable
500    *          DOCUMENT ME!
501    */
502   public static synchronized void addInternalFrame(
503           final JInternalFrame frame, String title, int w, int h,
504           boolean resizable)
505   {
506
507     // TODO: allow callers to determine X and Y position of frame (eg. via
508     // bounds object).
509     // TODO: consider fixing method to update entries in the window submenu with
510     // the current window title
511
512     frame.setTitle(title);
513     if (frame.getWidth() < 1 || frame.getHeight() < 1)
514     {
515       frame.setSize(w, h);
516     }
517     // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
518     // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
519     // IF JALVIEW IS RUNNING HEADLESS
520     // ///////////////////////////////////////////////
521     if (System.getProperty("java.awt.headless") != null
522             && System.getProperty("java.awt.headless").equals("true"))
523     {
524       return;
525     }
526
527     openFrameCount++;
528
529     frame.setVisible(true);
530     frame.setClosable(true);
531     frame.setResizable(resizable);
532     frame.setMaximizable(resizable);
533     frame.setIconifiable(resizable);
534     frame.setFrameIcon(null);
535
536     if (frame.getX() < 1 && frame.getY() < 1)
537     {
538       frame.setLocation(xOffset * openFrameCount, yOffset
539               * ((openFrameCount - 1) % 10) + yOffset);
540     }
541
542     final JMenuItem menuItem = new JMenuItem(title);
543     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
544     {
545       public void internalFrameActivated(
546               javax.swing.event.InternalFrameEvent evt)
547       {
548         JInternalFrame itf = desktop.getSelectedFrame();
549         if (itf != null)
550         {
551           itf.requestFocus();
552         }
553
554       }
555
556       public void internalFrameClosed(
557               javax.swing.event.InternalFrameEvent evt)
558       {
559         PaintRefresher.RemoveComponent(frame);
560         openFrameCount--;
561         windowMenu.remove(menuItem);
562         JInternalFrame itf = desktop.getSelectedFrame();
563         if (itf != null)
564         {
565           itf.requestFocus();
566         }
567         System.gc();
568       };
569     });
570
571     menuItem.addActionListener(new ActionListener()
572     {
573       public void actionPerformed(ActionEvent e)
574       {
575         try
576         {
577           frame.setSelected(true);
578           frame.setIcon(false);
579         } catch (java.beans.PropertyVetoException ex)
580         {
581
582         }
583       }
584     });
585     menuItem.addMouseListener(new MouseListener()
586     {
587       
588       @Override
589       public void mouseReleased(MouseEvent e)
590       {
591       }
592       
593       @Override
594       public void mousePressed(MouseEvent e)
595       {
596       }
597       
598       @Override
599       public void mouseExited(MouseEvent e)
600       {
601         try
602         {
603           frame.setSelected(false);
604         } catch (PropertyVetoException e1)
605         {
606         }
607       }
608       
609       @Override
610       public void mouseEntered(MouseEvent e)
611       {
612         try
613         {
614           frame.setSelected(true);
615         } catch (PropertyVetoException e1)
616         {
617         }
618       }
619       
620       @Override
621       public void mouseClicked(MouseEvent e)
622       {
623         
624       }
625     });
626
627     windowMenu.add(menuItem);
628
629     desktop.add(frame);
630     frame.toFront();
631     try
632     {
633       frame.setSelected(true);
634       frame.requestFocus();
635     } catch (java.beans.PropertyVetoException ve)
636     {
637     }
638     catch (java.lang.ClassCastException cex)
639     {
640       Cache.log.warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",cex);
641     }
642   }
643
644   public void lostOwnership(Clipboard clipboard, Transferable contents)
645   {
646     if (!internalCopy)
647     {
648       Desktop.jalviewClipboard = null;
649     }
650
651     internalCopy = false;
652   }
653
654   public void dragEnter(DropTargetDragEvent evt)
655   {
656   }
657
658   public void dragExit(DropTargetEvent evt)
659   {
660   }
661
662   public void dragOver(DropTargetDragEvent evt)
663   {
664   }
665
666   public void dropActionChanged(DropTargetDragEvent evt)
667   {
668   }
669
670   /**
671    * DOCUMENT ME!
672    * 
673    * @param evt
674    *          DOCUMENT ME!
675    */
676   public void drop(DropTargetDropEvent evt)
677   {
678     Transferable t = evt.getTransferable();
679     java.util.List files = null;
680     java.util.List protocols = null;
681
682     try
683     {
684       DataFlavor uriListFlavor = new DataFlavor(
685               "text/uri-list;class=java.lang.String");
686       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
687       {
688         // Works on Windows and MacOSX
689         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
690         files = (java.util.List) t
691                 .getTransferData(DataFlavor.javaFileListFlavor);
692       }
693       else if (t.isDataFlavorSupported(uriListFlavor))
694       {
695         // This is used by Unix drag system
696         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
697         String data = (String) t.getTransferData(uriListFlavor);
698         files = new java.util.ArrayList(1);
699         protocols = new java.util.ArrayList(1);
700         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
701                 data, "\r\n"); st.hasMoreTokens();)
702         {
703           String s = st.nextToken();
704           if (s.startsWith("#"))
705           {
706             // the line is a comment (as per the RFC 2483)
707             continue;
708           }
709           java.net.URI uri = new java.net.URI(s);
710           if (uri.getScheme().toLowerCase().startsWith("http"))
711           {
712             protocols.add(FormatAdapter.URL);
713             files.add(uri.toString());
714           }
715           else
716           {
717             // otherwise preserve old behaviour: catch all for file objects
718             java.io.File file = new java.io.File(uri);
719             protocols.add(FormatAdapter.FILE);
720             files.add(file.toString());
721           }
722         }
723       }
724     } catch (Exception e)
725     {
726     }
727
728     if (files != null)
729     {
730       try
731       {
732         for (int i = 0; i < files.size(); i++)
733         {
734           String file = files.get(i).toString();
735           String protocol = (protocols == null) ? FormatAdapter.FILE
736                   : (String) protocols.get(i);
737           String format = null;
738
739           if (file.endsWith(".jar"))
740           {
741             format = "Jalview";
742
743           }
744           else
745           {
746             format = new IdentifyFile().Identify(file, protocol);
747           }
748
749           new FileLoader().LoadFile(file, protocol, format);
750
751         }
752       } catch (Exception ex)
753       {
754       }
755     }
756   }
757
758   /**
759    * DOCUMENT ME!
760    * 
761    * @param e
762    *          DOCUMENT ME!
763    */
764   public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
765   {
766     JalviewFileChooser chooser = new JalviewFileChooser(
767             jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
768             jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
769             jalview.io.AppletFormatAdapter.READABLE_FNAMES,
770             jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
771
772     chooser.setFileView(new JalviewFileView());
773     chooser.setDialogTitle("Open local file");
774     chooser.setToolTipText("Open");
775
776     int value = chooser.showOpenDialog(this);
777
778     if (value == JalviewFileChooser.APPROVE_OPTION)
779     {
780       String choice = chooser.getSelectedFile().getPath();
781       jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
782               .getSelectedFile().getParent());
783
784       String format = null;
785       if (chooser.getSelectedFormat().equals("Jalview"))
786       {
787         format = "Jalview";
788       }
789       else
790       {
791         format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
792       }
793
794       if (viewport != null)
795       {
796         new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
797                 format);
798       }
799       else
800       {
801         new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
802       }
803     }
804   }
805
806   /**
807    * DOCUMENT ME!
808    * 
809    * @param e
810    *          DOCUMENT ME!
811    */
812   public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
813   {
814     // This construct allows us to have a wider textfield
815     // for viewing
816     JLabel label = new JLabel("Enter URL of Input File");
817     final JComboBox history = new JComboBox();
818
819     JPanel panel = new JPanel(new GridLayout(2, 1));
820     panel.add(label);
821     panel.add(history);
822     history.setPreferredSize(new Dimension(400, 20));
823     history.setEditable(true);
824     history.addItem("http://www.");
825
826     String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
827
828     StringTokenizer st;
829
830     if (historyItems != null)
831     {
832       st = new StringTokenizer(historyItems, "\t");
833
834       while (st.hasMoreTokens())
835       {
836         history.addItem(st.nextElement());
837       }
838     }
839
840     int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
841             "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
842
843     if (reply != JOptionPane.OK_OPTION)
844     {
845       return;
846     }
847
848     String url = history.getSelectedItem().toString();
849
850     if (url.toLowerCase().endsWith(".jar"))
851     {
852       if (viewport != null)
853       {
854         new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
855                 "Jalview");
856       }
857       else
858       {
859         new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
860       }
861     }
862     else
863     {
864       String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
865
866       if (format.equals("URL NOT FOUND"))
867       {
868         JOptionPane.showInternalMessageDialog(Desktop.desktop,
869                 "Couldn't locate " + url, "URL not found",
870                 JOptionPane.WARNING_MESSAGE);
871
872         return;
873       }
874
875       if (viewport != null)
876       {
877         new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
878       }
879       else
880       {
881         new FileLoader().LoadFile(url, FormatAdapter.URL, format);
882       }
883     }
884   }
885
886   /**
887    * DOCUMENT ME!
888    * 
889    * @param e
890    *          DOCUMENT ME!
891    */
892   public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
893   {
894     CutAndPasteTransfer cap = new CutAndPasteTransfer();
895     cap.setForInput(viewport);
896     Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
897   }
898
899   /*
900    * Exit the program
901    */
902   public void quit()
903   {
904     Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
905     jalview.bin.Cache
906             .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
907     jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
908             + "");
909     storeLastKnownDimensions("", new Rectangle(getBounds().x,
910             getBounds().y, getWidth(), getHeight()));
911
912     if (jconsole != null)
913     {
914       storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
915       jconsole.stopConsole();
916     }
917     System.exit(0);
918   }
919
920   private void storeLastKnownDimensions(String string, Rectangle jc)
921   {
922     jalview.bin.Cache.log.debug("Storing last known dimensions for "
923             + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
924             + " height:" + jc.height);
925
926     jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
927     jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
928     jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
929     jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
930   }
931
932   /**
933    * DOCUMENT ME!
934    * 
935    * @param e
936    *          DOCUMENT ME!
937    */
938   public void aboutMenuItem_actionPerformed(ActionEvent e)
939   {
940     StringBuffer message = new StringBuffer("Jalview version "
941             + jalview.bin.Cache.getProperty("VERSION") + "; last updated: "
942             + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
943
944     if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
945             jalview.bin.Cache.getProperty("VERSION")))
946     {
947       message.append("\n\n!! Jalview version "
948               + jalview.bin.Cache.getProperty("LATEST_VERSION")
949               + " is available for download from http://www.jalview.org !!\n");
950
951     }
952     // TODO: update this text for each release or centrally store it for lite
953     // and application
954     message.append("\nAuthors:  Jim Procter, Andrew Waterhouse, Michele Clamp, James Cuff, Steve Searle,\n    David Martin & Geoff Barton."
955             + "\nDevelopment managed by The Barton Group, University of Dundee, Scotland, UK.\n"
956             + "\nFor help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list\n"
957             + "\nIf  you use Jalview, please cite:"
958             + "\nWaterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
959             + "\nJalview Version 2 - a multiple sequence alignment editor and analysis workbench"
960             + "\nBioinformatics doi: 10.1093/bioinformatics/btp033");
961     JOptionPane.showInternalMessageDialog(Desktop.desktop,
962
963     message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
964   }
965
966   /**
967    * DOCUMENT ME!
968    * 
969    * @param e
970    *          DOCUMENT ME!
971    */
972   public void documentationMenuItem_actionPerformed(ActionEvent e)
973   {
974     try
975     {
976       ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
977       java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
978       javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
979
980       javax.help.HelpBroker hb = hs.createHelpBroker();
981       hb.setCurrentID("home");
982       hb.setDisplayed(true);
983     } catch (Exception ex)
984     {
985     }
986   }
987
988   public void closeAll_actionPerformed(ActionEvent e)
989   {
990     JInternalFrame[] frames = desktop.getAllFrames();
991     for (int i = 0; i < frames.length; i++)
992     {
993       try
994       {
995         frames[i].setClosed(true);
996       } catch (java.beans.PropertyVetoException ex)
997       {
998       }
999     }
1000     System.out.println("ALL CLOSED");
1001     if (v_client != null)
1002     {
1003       // TODO clear binding to vamsas document objects on close_all
1004
1005     }
1006   }
1007
1008   public void raiseRelated_actionPerformed(ActionEvent e)
1009   {
1010     reorderAssociatedWindows(false, false);
1011   }
1012
1013   public void minimizeAssociated_actionPerformed(ActionEvent e)
1014   {
1015     reorderAssociatedWindows(true, false);
1016   }
1017
1018   void closeAssociatedWindows()
1019   {
1020     reorderAssociatedWindows(false, true);
1021   }
1022
1023   /*
1024    * (non-Javadoc)
1025    * 
1026    * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1027    * ActionEvent)
1028    */
1029   protected void garbageCollect_actionPerformed(ActionEvent e)
1030   {
1031     // We simply collect the garbage
1032     jalview.bin.Cache.log.debug("Collecting garbage...");
1033     System.gc();
1034     jalview.bin.Cache.log.debug("Finished garbage collection.");
1035   }
1036
1037   /*
1038    * (non-Javadoc)
1039    * 
1040    * @see
1041    * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1042    * )
1043    */
1044   protected void showMemusage_actionPerformed(ActionEvent e)
1045   {
1046     desktop.showMemoryUsage(showMemusage.isSelected());
1047   }
1048
1049   /*
1050    * (non-Javadoc)
1051    * 
1052    * @see
1053    * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1054    * )
1055    */
1056   protected void showConsole_actionPerformed(ActionEvent e)
1057   {
1058     showConsole(showConsole.isSelected());
1059   }
1060
1061   Console jconsole = null;
1062
1063   /**
1064    * control whether the java console is visible or not
1065    * 
1066    * @param selected
1067    */
1068   void showConsole(boolean selected)
1069   {
1070     showConsole.setSelected(selected);
1071     // TODO: decide if we should update properties file
1072     Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1073             .toString());
1074     jconsole.setVisible(selected);
1075   }
1076
1077   void reorderAssociatedWindows(boolean minimize, boolean close)
1078   {
1079     JInternalFrame[] frames = desktop.getAllFrames();
1080     if (frames == null || frames.length < 1)
1081     {
1082       return;
1083     }
1084
1085     AlignViewport source = null, target = null;
1086     if (frames[0] instanceof AlignFrame)
1087     {
1088       source = ((AlignFrame) frames[0]).getCurrentView();
1089     }
1090     else if (frames[0] instanceof TreePanel)
1091     {
1092       source = ((TreePanel) frames[0]).getViewPort();
1093     }
1094     else if (frames[0] instanceof PCAPanel)
1095     {
1096       source = ((PCAPanel) frames[0]).av;
1097     }
1098     else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1099     {
1100       source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1101     }
1102
1103     if (source != null)
1104     {
1105       for (int i = 0; i < frames.length; i++)
1106       {
1107         target = null;
1108         if (frames[i] == null)
1109         {
1110           continue;
1111         }
1112         if (frames[i] instanceof AlignFrame)
1113         {
1114           target = ((AlignFrame) frames[i]).getCurrentView();
1115         }
1116         else if (frames[i] instanceof TreePanel)
1117         {
1118           target = ((TreePanel) frames[i]).getViewPort();
1119         }
1120         else if (frames[i] instanceof PCAPanel)
1121         {
1122           target = ((PCAPanel) frames[i]).av;
1123         }
1124         else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1125         {
1126           target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1127         }
1128
1129         if (source == target)
1130         {
1131           try
1132           {
1133             if (close)
1134             {
1135               frames[i].setClosed(true);
1136             }
1137             else
1138             {
1139               frames[i].setIcon(minimize);
1140               if (!minimize)
1141               {
1142                 frames[i].toFront();
1143               }
1144             }
1145
1146           } catch (java.beans.PropertyVetoException ex)
1147           {
1148           }
1149         }
1150       }
1151     }
1152   }
1153
1154   /**
1155    * DOCUMENT ME!
1156    * 
1157    * @param e
1158    *          DOCUMENT ME!
1159    */
1160   protected void preferences_actionPerformed(ActionEvent e)
1161   {
1162     new Preferences();
1163   }
1164
1165   /**
1166    * DOCUMENT ME!
1167    * 
1168    * @param e
1169    *          DOCUMENT ME!
1170    */
1171   public void saveState_actionPerformed(ActionEvent e)
1172   {
1173     JalviewFileChooser chooser = new JalviewFileChooser(
1174             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1175             { "jar" }, new String[]
1176             { "Jalview Project" }, "Jalview Project");
1177
1178     chooser.setFileView(new JalviewFileView());
1179     chooser.setDialogTitle("Save State");
1180
1181     int value = chooser.showSaveDialog(this);
1182
1183     if (value == JalviewFileChooser.APPROVE_OPTION)
1184     {
1185       final Desktop me = this;
1186       final java.io.File choice = chooser.getSelectedFile();
1187       new Thread(new Runnable()
1188       {
1189         public void run()
1190         {
1191
1192       setProgressBar("Saving jalview project " + choice.getName(),
1193               choice.hashCode());
1194       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1195       // TODO catch and handle errors for savestate
1196       // TODO prevent user from messing with the Desktop whilst we're saving
1197       try
1198       {
1199         new Jalview2XML().SaveState(choice);
1200       } catch (OutOfMemoryError oom)
1201       {
1202         new OOMWarning(
1203                 "Whilst saving current state to " + choice.getName(), oom);
1204       } catch (Exception ex)
1205       {
1206         Cache.log
1207                 .error("Problems whilst trying to save to "
1208                         + choice.getName(), ex);
1209         JOptionPane.showMessageDialog(me,
1210                 "Error whilst saving current state to " + choice.getName(),
1211                 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1212       }
1213       setProgressBar(null, choice.hashCode());
1214         }
1215       }).start();
1216     }
1217   }
1218
1219   /**
1220    * DOCUMENT ME!
1221    * 
1222    * @param e
1223    *          DOCUMENT ME!
1224    */
1225   public void loadState_actionPerformed(ActionEvent e)
1226   {
1227     JalviewFileChooser chooser = new JalviewFileChooser(
1228             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1229             { "jar" }, new String[]
1230             { "Jalview Project" }, "Jalview Project");
1231     chooser.setFileView(new JalviewFileView());
1232     chooser.setDialogTitle("Restore state");
1233
1234     int value = chooser.showOpenDialog(this);
1235
1236     if (value == JalviewFileChooser.APPROVE_OPTION)
1237     {
1238       final String choice = chooser.getSelectedFile().getAbsolutePath();
1239       jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1240               .getSelectedFile().getParent());
1241       new Thread(new Runnable()
1242       {
1243         public void run()
1244         {
1245           setProgressBar("loading jalview project " + choice,
1246                   choice.hashCode());
1247           try
1248           {
1249             new Jalview2XML().LoadJalviewAlign(choice);
1250           } catch (OutOfMemoryError oom)
1251           {
1252             new OOMWarning("Whilst loading project from " + choice, oom);
1253           } catch (Exception ex)
1254           {
1255             Cache.log.error("Problems whilst loading project from "
1256                     + choice, ex);
1257             JOptionPane.showMessageDialog(Desktop.desktop,
1258                     "Error whilst loading project from " + choice,
1259                     "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1260           }
1261           setProgressBar(null, choice.hashCode());
1262         }
1263       }).start();
1264     }
1265   }
1266
1267   public void inputSequence_actionPerformed(ActionEvent e)
1268   {
1269     new SequenceFetcher(this);
1270   }
1271
1272   JPanel progressPanel;
1273
1274   public void startLoading(final String fileName)
1275   {
1276     if (fileLoadingCount == 0)
1277     {
1278       addProgressPanel("Loading File: " + fileName + "   ");
1279
1280     }
1281     fileLoadingCount++;
1282   }
1283
1284   private JProgressBar addProgressPanel(String string)
1285   {
1286     if (progressPanel == null)
1287     {
1288       progressPanel = new JPanel(new BorderLayout());
1289       totalProgressCount = 0;
1290     }
1291     JProgressBar progressBar = new JProgressBar();
1292     progressBar.setIndeterminate(true);
1293
1294     progressPanel.add(new JLabel(string), BorderLayout.WEST);
1295
1296     progressPanel.add(progressBar, BorderLayout.CENTER);
1297
1298     instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1299     totalProgressCount++;
1300     validate();
1301     return progressBar;
1302   }
1303
1304   int totalProgressCount = 0;
1305
1306   private void removeProgressPanel(JProgressBar progbar)
1307   {
1308     if (progressPanel != null)
1309     {
1310       progressPanel.remove(progbar);
1311       if (--totalProgressCount < 1)
1312       {
1313         this.getContentPane().remove(progressPanel);
1314         progressPanel = null;
1315       }
1316     }
1317     validate();
1318   }
1319
1320   public void stopLoading()
1321   {
1322     fileLoadingCount--;
1323     if (fileLoadingCount < 1)
1324     {
1325       if (progressPanel != null)
1326       {
1327         this.getContentPane().remove(progressPanel);
1328         progressPanel = null;
1329       }
1330       fileLoadingCount = 0;
1331     }
1332     validate();
1333   }
1334
1335   public static int getViewCount(String alignmentId)
1336   {
1337     AlignViewport[] aps = getViewports(alignmentId);
1338     return (aps == null) ? 0 : aps.length;
1339   }
1340
1341   /**
1342    * 
1343    * @param alignmentId
1344    * @return all AlignmentPanels concerning the alignmentId sequence set
1345    */
1346   public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1347   {
1348     int count = 0;
1349     if (Desktop.desktop == null)
1350     {
1351       // no frames created and in headless mode
1352       // TODO: verify that frames are recoverable when in headless mode
1353       return null;
1354     }
1355     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1356     ArrayList aps = new ArrayList();
1357     for (int t = 0; t < frames.length; t++)
1358     {
1359       if (frames[t] instanceof AlignFrame)
1360       {
1361         AlignFrame af = (AlignFrame) frames[t];
1362         for (int a = 0; a < af.alignPanels.size(); a++)
1363         {
1364           if (alignmentId
1365                   .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1366                           .getSequenceSetId()))
1367           {
1368             aps.add(af.alignPanels.elementAt(a));
1369           }
1370         }
1371       }
1372     }
1373     if (aps.size() == 0)
1374     {
1375       return null;
1376     }
1377     AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1378     for (int t = 0; t < vap.length; t++)
1379     {
1380       vap[t] = (AlignmentPanel) aps.get(t);
1381     }
1382     return vap;
1383   }
1384
1385   /**
1386    * get all the viewports on an alignment.
1387    * 
1388    * @param sequenceSetId
1389    *          unique alignment id
1390    * @return all viewports on the alignment bound to sequenceSetId
1391    */
1392   public static AlignViewport[] getViewports(String sequenceSetId)
1393   {
1394     Vector viewp = new Vector();
1395     if (desktop != null)
1396     {
1397       javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1398
1399       for (int t = 0; t < frames.length; t++)
1400       {
1401         if (frames[t] instanceof AlignFrame)
1402         {
1403           AlignFrame afr = ((AlignFrame) frames[t]);
1404           if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1405           {
1406             if (afr.alignPanels != null)
1407             {
1408               for (int a = 0; a < afr.alignPanels.size(); a++)
1409               {
1410                 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1411                         .elementAt(a)).av.getSequenceSetId()))
1412                 {
1413                   viewp.addElement(((AlignmentPanel) afr.alignPanels
1414                           .elementAt(a)).av);
1415                 }
1416               }
1417             }
1418             else
1419             {
1420               viewp.addElement(((AlignFrame) frames[t]).getViewport());
1421             }
1422           }
1423         }
1424       }
1425       if (viewp.size() > 0)
1426       {
1427         AlignViewport[] vp = new AlignViewport[viewp.size()];
1428         viewp.copyInto(vp);
1429         return vp;
1430       }
1431     }
1432     return null;
1433   }
1434
1435   public void explodeViews(AlignFrame af)
1436   {
1437     int size = af.alignPanels.size();
1438     if (size < 2)
1439     {
1440       return;
1441     }
1442
1443     for (int i = 0; i < size; i++)
1444     {
1445       AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1446       AlignFrame newaf = new AlignFrame(ap);
1447       if (ap.av.explodedPosition != null
1448               && !ap.av.explodedPosition.equals(af.getBounds()))
1449       {
1450         newaf.setBounds(ap.av.explodedPosition);
1451       }
1452
1453       ap.av.gatherViewsHere = false;
1454
1455       addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1456               AlignFrame.DEFAULT_HEIGHT);
1457     }
1458
1459     af.alignPanels.clear();
1460     af.closeMenuItem_actionPerformed(true);
1461
1462   }
1463
1464   public void gatherViews(AlignFrame source)
1465   {
1466     source.viewport.gatherViewsHere = true;
1467     source.viewport.explodedPosition = source.getBounds();
1468     JInternalFrame[] frames = desktop.getAllFrames();
1469     String viewId = source.viewport.sequenceSetID;
1470
1471     for (int t = 0; t < frames.length; t++)
1472     {
1473       if (frames[t] instanceof AlignFrame && frames[t] != source)
1474       {
1475         AlignFrame af = (AlignFrame) frames[t];
1476         boolean gatherThis = false;
1477         for (int a = 0; a < af.alignPanels.size(); a++)
1478         {
1479           AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1480           if (viewId.equals(ap.av.getSequenceSetId()))
1481           {
1482             gatherThis = true;
1483             ap.av.gatherViewsHere = false;
1484             ap.av.explodedPosition = af.getBounds();
1485             source.addAlignmentPanel(ap, false);
1486           }
1487         }
1488
1489         if (gatherThis)
1490         {
1491           af.alignPanels.clear();
1492           af.closeMenuItem_actionPerformed(true);
1493         }
1494       }
1495     }
1496
1497   }
1498
1499   jalview.gui.VamsasApplication v_client = null;
1500
1501   public void vamsasImport_actionPerformed(ActionEvent e)
1502   {
1503     if (v_client == null)
1504     {
1505       // Load and try to start a session.
1506       JalviewFileChooser chooser = new JalviewFileChooser(
1507               jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1508
1509       chooser.setFileView(new JalviewFileView());
1510       chooser.setDialogTitle("Open a saved VAMSAS session");
1511       chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1512
1513       int value = chooser.showOpenDialog(this);
1514
1515       if (value == JalviewFileChooser.APPROVE_OPTION)
1516       {
1517         String fle = chooser.getSelectedFile().toString();
1518         if (!vamsasImport(chooser.getSelectedFile()))
1519         {
1520           JOptionPane.showInternalMessageDialog(Desktop.desktop,
1521                   "Couldn't import '" + fle + "' as a new vamsas session.",
1522                   "Vamsas Document Import Failed",
1523                   JOptionPane.ERROR_MESSAGE);
1524         }
1525       }
1526     }
1527     else
1528     {
1529       jalview.bin.Cache.log
1530               .error("Implementation error - load session from a running session is not supported.");
1531     }
1532   }
1533
1534   /**
1535    * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1536    * 
1537    * @param file
1538    * @return true if import was a success and a session was started.
1539    */
1540   public boolean vamsasImport(URL url)
1541   {
1542     // TODO: create progress bar
1543     if (v_client != null)
1544     {
1545
1546       jalview.bin.Cache.log
1547               .error("Implementation error - load session from a running session is not supported.");
1548       return false;
1549     }
1550
1551     try
1552     {
1553       // copy the URL content to a temporary local file
1554       // TODO: be a bit cleverer here with nio (?!)
1555       File file = File.createTempFile("vdocfromurl", ".vdj");
1556       FileOutputStream fos = new FileOutputStream(file);
1557       BufferedInputStream bis = new BufferedInputStream(url.openStream());
1558       byte[] buffer = new byte[2048];
1559       int ln;
1560       while ((ln = bis.read(buffer)) > -1)
1561       {
1562         fos.write(buffer, 0, ln);
1563       }
1564       bis.close();
1565       fos.close();
1566       v_client = new jalview.gui.VamsasApplication(this, file,
1567               url.toExternalForm());
1568     } catch (Exception ex)
1569     {
1570       jalview.bin.Cache.log.error(
1571               "Failed to create new vamsas session from contents of URL "
1572                       + url, ex);
1573       return false;
1574     }
1575     setupVamsasConnectedGui();
1576     v_client.initial_update(); // TODO: thread ?
1577     return v_client.inSession();
1578   }
1579
1580   /**
1581    * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1582    * 
1583    * @param file
1584    * @return true if import was a success and a session was started.
1585    */
1586   public boolean vamsasImport(File file)
1587   {
1588     if (v_client != null)
1589     {
1590
1591       jalview.bin.Cache.log
1592               .error("Implementation error - load session from a running session is not supported.");
1593       return false;
1594     }
1595
1596     setProgressBar("Importing VAMSAS session from " + file.getName(),
1597             file.hashCode());
1598     try
1599     {
1600       v_client = new jalview.gui.VamsasApplication(this, file, null);
1601     } catch (Exception ex)
1602     {
1603       setProgressBar("Importing VAMSAS session from " + file.getName(),
1604               file.hashCode());
1605       jalview.bin.Cache.log.error(
1606               "New vamsas session from existing session file failed:", ex);
1607       return false;
1608     }
1609     setupVamsasConnectedGui();
1610     v_client.initial_update(); // TODO: thread ?
1611     setProgressBar("Importing VAMSAS session from " + file.getName(),
1612             file.hashCode());
1613     return v_client.inSession();
1614   }
1615
1616   public boolean joinVamsasSession(String mysesid)
1617   {
1618     if (v_client != null)
1619     {
1620       throw new Error(
1621               "Trying to join a vamsas session when another is already connected.");
1622     }
1623     if (mysesid == null)
1624     {
1625       throw new Error("Invalid vamsas session id.");
1626     }
1627     v_client = new VamsasApplication(this, mysesid);
1628     setupVamsasConnectedGui();
1629     v_client.initial_update();
1630     return (v_client.inSession());
1631   }
1632
1633   public void vamsasStart_actionPerformed(ActionEvent e)
1634   {
1635     if (v_client == null)
1636     {
1637       // Start a session.
1638       // we just start a default session for moment.
1639       /*
1640        * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1641        * getProperty("LAST_DIRECTORY"));
1642        * 
1643        * chooser.setFileView(new JalviewFileView());
1644        * chooser.setDialogTitle("Load Vamsas file");
1645        * chooser.setToolTipText("Import");
1646        * 
1647        * int value = chooser.showOpenDialog(this);
1648        * 
1649        * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1650        * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1651        */
1652       v_client = new VamsasApplication(this);
1653       setupVamsasConnectedGui();
1654       v_client.initial_update(); // TODO: thread ?
1655     }
1656     else
1657     {
1658       // store current data in session.
1659       v_client.push_update(); // TODO: thread
1660     }
1661   }
1662
1663   protected void setupVamsasConnectedGui()
1664   {
1665     vamsasStart.setText("Session Update");
1666     vamsasSave.setVisible(true);
1667     vamsasStop.setVisible(true);
1668     vamsasImport.setVisible(false); // Document import to existing session is
1669     // not possible for vamsas-client-1.0.
1670   }
1671
1672   protected void setupVamsasDisconnectedGui()
1673   {
1674     vamsasSave.setVisible(false);
1675     vamsasStop.setVisible(false);
1676     vamsasImport.setVisible(true);
1677     vamsasStart.setText("New Vamsas Session");
1678   }
1679
1680   public void vamsasStop_actionPerformed(ActionEvent e)
1681   {
1682     if (v_client != null)
1683     {
1684       v_client.end_session();
1685       v_client = null;
1686       setupVamsasDisconnectedGui();
1687     }
1688   }
1689
1690   protected void buildVamsasStMenu()
1691   {
1692     if (v_client == null)
1693     {
1694       String[] sess = null;
1695       try
1696       {
1697         sess = VamsasApplication.getSessionList();
1698       } catch (Exception e)
1699       {
1700         jalview.bin.Cache.log.warn(
1701                 "Problem getting current sessions list.", e);
1702         sess = null;
1703       }
1704       if (sess != null)
1705       {
1706         jalview.bin.Cache.log.debug("Got current sessions list: "
1707                 + sess.length + " entries.");
1708         VamsasStMenu.removeAll();
1709         for (int i = 0; i < sess.length; i++)
1710         {
1711           JMenuItem sessit = new JMenuItem();
1712           sessit.setText(sess[i]);
1713           sessit.setToolTipText("Connect to session " + sess[i]);
1714           final Desktop dsktp = this;
1715           final String mysesid = sess[i];
1716           sessit.addActionListener(new ActionListener()
1717           {
1718
1719             public void actionPerformed(ActionEvent e)
1720             {
1721               if (dsktp.v_client == null)
1722               {
1723                 Thread rthr = new Thread(new Runnable()
1724                 {
1725
1726                   public void run()
1727                   {
1728                     dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1729                     dsktp.setupVamsasConnectedGui();
1730                     dsktp.v_client.initial_update();
1731                   }
1732
1733                 });
1734                 rthr.start();
1735               }
1736             };
1737           });
1738           VamsasStMenu.add(sessit);
1739         }
1740         // don't show an empty menu.
1741         VamsasStMenu.setVisible(sess.length > 0);
1742
1743       }
1744       else
1745       {
1746         jalview.bin.Cache.log.debug("No current vamsas sessions.");
1747         VamsasStMenu.removeAll();
1748         VamsasStMenu.setVisible(false);
1749       }
1750     }
1751     else
1752     {
1753       // Not interested in the content. Just hide ourselves.
1754       VamsasStMenu.setVisible(false);
1755     }
1756   }
1757
1758   public void vamsasSave_actionPerformed(ActionEvent e)
1759   {
1760     if (v_client != null)
1761     {
1762       JalviewFileChooser chooser = new JalviewFileChooser(
1763               jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1764               { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1765               new String[]
1766               { "Vamsas Document" }, "Vamsas Document");
1767
1768       chooser.setFileView(new JalviewFileView());
1769       chooser.setDialogTitle("Save Vamsas Document Archive");
1770
1771       int value = chooser.showSaveDialog(this);
1772
1773       if (value == JalviewFileChooser.APPROVE_OPTION)
1774       {
1775         java.io.File choice = chooser.getSelectedFile();
1776         JProgressBar progpanel = addProgressPanel("Saving VAMSAS Document to "
1777                 + choice.getName());
1778         jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1779         String warnmsg = null;
1780         String warnttl = null;
1781         try
1782         {
1783           v_client.vclient.storeDocument(choice);
1784         } catch (Error ex)
1785         {
1786           warnttl = "Serious Problem saving Vamsas Document";
1787           warnmsg = ex.toString();
1788           jalview.bin.Cache.log.error("Error Whilst saving document to "
1789                   + choice, ex);
1790
1791         } catch (Exception ex)
1792         {
1793           warnttl = "Problem saving Vamsas Document.";
1794           warnmsg = ex.toString();
1795           jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1796                   + choice, ex);
1797
1798         }
1799         removeProgressPanel(progpanel);
1800         if (warnmsg != null)
1801         {
1802           JOptionPane.showInternalMessageDialog(Desktop.desktop,
1803
1804           warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1805         }
1806       }
1807     }
1808   }
1809
1810   JProgressBar vamUpdate = null;
1811
1812   /**
1813    * hide vamsas user gui bits when a vamsas document event is being handled.
1814    * 
1815    * @param b
1816    *          true to hide gui, false to reveal gui
1817    */
1818   public void setVamsasUpdate(boolean b)
1819   {
1820     jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
1821             + (b ? "in progress" : "finished"));
1822
1823     if (vamUpdate != null)
1824     {
1825       this.removeProgressPanel(vamUpdate);
1826     }
1827     if (b)
1828     {
1829       vamUpdate = this.addProgressPanel("Updating vamsas session");
1830     }
1831     vamsasStart.setVisible(!b);
1832     vamsasStop.setVisible(!b);
1833     vamsasSave.setVisible(!b);
1834   }
1835
1836   public JInternalFrame[] getAllFrames()
1837   {
1838     return desktop.getAllFrames();
1839   }
1840
1841   /**
1842    * Checks the given url to see if it gives a response indicating that the user
1843    * should be informed of a new questionnaire.
1844    * 
1845    * @param url
1846    */
1847   public void checkForQuestionnaire(String url)
1848   {
1849     UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
1850     // javax.swing.SwingUtilities.invokeLater(jvq);
1851     new Thread(jvq).start();
1852   }
1853
1854   /**
1855    * Proxy class for JDesktopPane which optionally displays the current memory
1856    * usage and highlights the desktop area with a red bar if free memory runs
1857    * low.
1858    * 
1859    * @author AMW
1860    */
1861   public class MyDesktopPane extends JDesktopPane implements Runnable
1862   {
1863
1864     boolean showMemoryUsage = false;
1865
1866     Runtime runtime;
1867
1868     java.text.NumberFormat df;
1869
1870     float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
1871             percentUsage;
1872
1873     public MyDesktopPane(boolean showMemoryUsage)
1874     {
1875       showMemoryUsage(showMemoryUsage);
1876     }
1877
1878     public void showMemoryUsage(boolean showMemoryUsage)
1879     {
1880       this.showMemoryUsage = showMemoryUsage;
1881       if (showMemoryUsage)
1882       {
1883         Thread worker = new Thread(this);
1884         worker.start();
1885       }
1886     }
1887
1888     public boolean isShowMemoryUsage()
1889     {
1890       return showMemoryUsage;
1891     }
1892
1893     public void run()
1894     {
1895       df = java.text.NumberFormat.getNumberInstance();
1896       df.setMaximumFractionDigits(2);
1897       runtime = Runtime.getRuntime();
1898
1899       while (showMemoryUsage)
1900       {
1901         try
1902         {
1903           maxMemory = runtime.maxMemory() / 1048576f;
1904           allocatedMemory = runtime.totalMemory() / 1048576f;
1905           freeMemory = runtime.freeMemory() / 1048576f;
1906           totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
1907
1908           percentUsage = (totalFreeMemory / maxMemory) * 100;
1909
1910           // if (percentUsage < 20)
1911           {
1912             // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
1913             // Color.red);
1914             // instance.set.setBorder(border1);
1915           }
1916           repaint();
1917           // sleep after showing usage
1918           Thread.sleep(3000);
1919         } catch (Exception ex)
1920         {
1921           ex.printStackTrace();
1922         }
1923       }
1924     }
1925
1926     public void paintComponent(Graphics g)
1927     {
1928       if (showMemoryUsage && g != null && df != null)
1929       {
1930         if (percentUsage < 20)
1931           g.setColor(Color.red);
1932         FontMetrics fm = g.getFontMetrics();
1933         if (fm != null)
1934         {
1935           g.drawString(
1936                   "Total Free Memory: " + df.format(totalFreeMemory)
1937                           + "MB; Max Memory: " + df.format(maxMemory)
1938                           + "MB; " + df.format(percentUsage) + "%", 10,
1939                   getHeight() - fm.getHeight());
1940         }
1941       }
1942     }
1943
1944   }
1945
1946   protected JMenuItem groovyShell;
1947
1948   public void doGroovyCheck()
1949   {
1950     if (jalview.bin.Cache.groovyJarsPresent())
1951     {
1952       groovyShell = new JMenuItem();
1953       groovyShell.setText("Groovy Console...");
1954       groovyShell.addActionListener(new ActionListener()
1955       {
1956         public void actionPerformed(ActionEvent e)
1957         {
1958           groovyShell_actionPerformed(e);
1959         }
1960       });
1961       toolsMenu.add(groovyShell);
1962       groovyShell.setVisible(true);
1963     }
1964   }
1965
1966   /**
1967    * Accessor method to quickly get all the AlignmentFrames loaded.
1968    */
1969   public static AlignFrame[] getAlignframes()
1970   {
1971     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1972
1973     if (frames == null)
1974     {
1975       return null;
1976     }
1977     Vector avp = new Vector();
1978     try
1979     {
1980       // REVERSE ORDER
1981       for (int i = frames.length - 1; i > -1; i--)
1982       {
1983         if (frames[i] instanceof AlignFrame)
1984         {
1985           AlignFrame af = (AlignFrame) frames[i];
1986           avp.addElement(af);
1987         }
1988       }
1989     } catch (Exception ex)
1990     {
1991       ex.printStackTrace();
1992     }
1993     if (avp.size() == 0)
1994     {
1995       return null;
1996     }
1997     AlignFrame afs[] = new AlignFrame[avp.size()];
1998     for (int i = 0, j = avp.size(); i < j; i++)
1999     {
2000       afs[i] = (AlignFrame) avp.elementAt(i);
2001     }
2002     avp.clear();
2003     return afs;
2004   }
2005   public AppJmol[] getJmols()
2006   {
2007     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2008
2009     if (frames == null)
2010     {
2011       return null;
2012     }
2013     Vector avp = new Vector();
2014     try
2015     {
2016       // REVERSE ORDER
2017       for (int i = frames.length - 1; i > -1; i--)
2018       {
2019         if (frames[i] instanceof AppJmol)
2020         {
2021           AppJmol af = (AppJmol) frames[i];
2022           avp.addElement(af);
2023         }
2024       }
2025     } catch (Exception ex)
2026     {
2027       ex.printStackTrace();
2028     }
2029     if (avp.size() == 0)
2030     {
2031       return null;
2032     }
2033     AppJmol afs[] = new AppJmol[avp.size()];
2034     for (int i = 0, j = avp.size(); i < j; i++)
2035     {
2036       afs[i] = (AppJmol) avp.elementAt(i);
2037     }
2038     avp.clear();
2039     return afs;
2040   }
2041
2042   /**
2043    * Add Groovy Support to Jalview
2044    */
2045   public void groovyShell_actionPerformed(ActionEvent e)
2046   {
2047     // use reflection to avoid creating compilation dependency.
2048     if (!jalview.bin.Cache.groovyJarsPresent())
2049     {
2050       throw new Error(
2051               "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2052     }
2053     try
2054     {
2055       Class gcClass = Desktop.class.getClassLoader().loadClass(
2056               "groovy.ui.Console");
2057       Constructor gccons = gcClass.getConstructor(null);
2058       java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2059               new Class[]
2060               { String.class, Object.class });
2061       java.lang.reflect.Method run = gcClass.getMethod("run", null);
2062       Object gc = gccons.newInstance(null);
2063       setvar.invoke(gc, new Object[]
2064       { "Jalview", this });
2065       run.invoke(gc, null);
2066     } catch (Exception ex)
2067     {
2068       jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2069       JOptionPane
2070               .showInternalMessageDialog(
2071                       Desktop.desktop,
2072
2073                       "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2074                       "Jalview Groovy Support Failed",
2075                       JOptionPane.ERROR_MESSAGE);
2076     }
2077   }
2078
2079   /**
2080    * Progress bars managed by the IProgressIndicator method.
2081    */
2082   private Hashtable progressBars, progressBarHandlers;
2083
2084   /*
2085    * (non-Javadoc)
2086    * 
2087    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2088    */
2089   public void setProgressBar(String message, long id)
2090   {
2091     if (progressBars == null)
2092     {
2093       progressBars = new Hashtable();
2094       progressBarHandlers = new Hashtable();
2095     }
2096
2097     if (progressBars.get(new Long(id)) != null)
2098     {
2099       JProgressBar progressPanel = (JProgressBar) progressBars
2100               .remove(new Long(id));
2101       if (progressBarHandlers.contains(new Long(id)))
2102       {
2103         progressBarHandlers.remove(new Long(id));
2104       }
2105       removeProgressPanel(progressPanel);
2106     }
2107     else
2108     {
2109       progressBars.put(new Long(id), addProgressPanel(message));
2110     }
2111   }
2112
2113   /*
2114    * (non-Javadoc)
2115    * 
2116    * @see jalview.gui.IProgressIndicator#registerHandler(long,
2117    * jalview.gui.IProgressIndicatorHandler)
2118    */
2119   public void registerHandler(final long id,
2120           final IProgressIndicatorHandler handler)
2121   {
2122     if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2123     {
2124       throw new Error(
2125               "call setProgressBar before registering the progress bar's handler.");
2126     }
2127     progressBarHandlers.put(new Long(id), handler);
2128     final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2129     if (handler.canCancel())
2130     {
2131       JButton cancel = new JButton("Cancel");
2132       final IProgressIndicator us = this;
2133       cancel.addActionListener(new ActionListener()
2134       {
2135
2136         public void actionPerformed(ActionEvent e)
2137         {
2138           handler.cancelActivity(id);
2139           us.setProgressBar(
2140                   "Cancelled "
2141                           + ((JLabel) progressPanel.getComponent(0))
2142                                   .getText(), id);
2143         }
2144       });
2145       progressPanel.add(cancel, BorderLayout.EAST);
2146     }
2147   }
2148
2149   /**
2150    * This will return the first AlignFrame viewing AlignViewport av. It will
2151    * break if there are more than one AlignFrames viewing a particular av. This
2152    * 
2153    * @param av
2154    * @return alignFrame for av
2155    */
2156   public static AlignFrame getAlignFrameFor(AlignViewport av)
2157   {
2158     if (desktop != null)
2159     {
2160       AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2161       for (int panel = 0; aps != null && panel < aps.length; panel++)
2162       {
2163         if (aps[panel] != null && aps[panel].av == av)
2164         {
2165           return aps[panel].alignFrame;
2166         }
2167       }
2168     }
2169     return null;
2170   }
2171
2172   public VamsasApplication getVamsasApplication()
2173   {
2174     return v_client;
2175
2176   }
2177
2178   /**
2179    * flag set if jalview GUI is being operated programmatically
2180    */
2181   private boolean inBatchMode = false;
2182
2183   /**
2184    * check if jalview GUI is being operated programmatically
2185    * 
2186    * @return inBatchMode
2187    */
2188   public boolean isInBatchMode()
2189   {
2190     return inBatchMode;
2191   }
2192
2193   /**
2194    * set flag if jalview GUI is being operated programmatically
2195    * 
2196    * @param inBatchMode
2197    */
2198   public void setInBatchMode(boolean inBatchMode)
2199   {
2200     this.inBatchMode = inBatchMode;
2201   }
2202
2203   public void startServiceDiscovery()
2204   {
2205     startServiceDiscovery(false);
2206   }
2207
2208   public void startServiceDiscovery(boolean blocking)
2209   {
2210     boolean alive = true;
2211     Thread t0 = null, t1 = null, t2 = null;
2212
2213     // todo: changesupport handlers need to be transferred
2214     if (discoverer == null)
2215     {
2216       discoverer = new jalview.ws.jws1.Discoverer();
2217       // register PCS handler for desktop.
2218       discoverer.addPropertyChangeListener(changeSupport);
2219     }
2220     if (Cache.getDefault("SHOW_JWS1_SERVICES", true))
2221     {
2222       (t0 = new Thread(discoverer)).start();
2223     }
2224
2225     try
2226     {
2227       if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2228       {
2229         // EnfinEnvision web service menu entries are rebuild every time the
2230         // menu is shown, so no changeSupport events are needed.
2231         jalview.ws.EnfinEnvision2OneWay.getInstance();
2232         (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2233                 .start();
2234       }
2235     } catch (Exception e)
2236     {
2237       Cache.log
2238               .info("Exception when trying to launch Envision2 workflow discovery.",
2239                       e);
2240       Cache.log.info(e.getStackTrace());
2241     }
2242     if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2243     {
2244       if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2245       {
2246         jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2247       }
2248       t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2249               changeSupport);
2250       
2251     }
2252     Thread t3=null;
2253     {
2254       // TODO: do rest service discovery
2255     }
2256     if (blocking)
2257     {
2258       while (alive)
2259       {
2260         try
2261         {
2262           Thread.sleep(15);
2263         } catch (Exception e)
2264         {
2265         }
2266         alive = (t1 != null && t1.isAlive())
2267                 || (t2 != null && t2.isAlive())
2268                 || (t3 != null && t3.isAlive())
2269                 || (t0 != null && t0.isAlive());
2270       }
2271     }
2272   }
2273
2274   /**
2275    * called to check if the service discovery process completed successfully.
2276    * 
2277    * @param evt
2278    */
2279   protected void JalviewServicesChanged(PropertyChangeEvent evt)
2280   {
2281     if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2282     {
2283       final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2284               .getErrorMessages();
2285       if (ermsg != null)
2286       {
2287         if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2288         {
2289         if (serviceChangedDialog == null)
2290         {
2291           // only run if we aren't already displaying one of these.
2292           javax.swing.SwingUtilities
2293                   .invokeLater(serviceChangedDialog = new Runnable()
2294                   {
2295                     public void run()
2296                     {
2297
2298                       JOptionPane
2299                               .showInternalMessageDialog(
2300                                       Desktop.desktop,
2301                                       ermsg
2302                                                 + "It may be that you have invalid JABA URLs\nin your web service preferences.\n\nGo to the Web services tab of the\nTools->Preferences dialog box to change them.\n",
2303                                       "Preferences Problem",
2304                                       JOptionPane.WARNING_MESSAGE);
2305                       serviceChangedDialog = null;
2306
2307                     }
2308                   });
2309         }
2310       }
2311         else
2312         {
2313           Cache.log
2314                   .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2315                           + ermsg);
2316         }
2317       }
2318     }
2319   }
2320
2321   private Runnable serviceChangedDialog = null;
2322
2323   /**
2324    * start a thread to open a URL in the configured browser. Pops up a warning
2325    * dialog to the user if there is an exception when calling out to the browser
2326    * to open the URL.
2327    * 
2328    * @param url
2329    */
2330   public static void showUrl(final String url)
2331   {
2332     showUrl(url, Desktop.instance);
2333   }
2334   /**
2335    * Like showUrl but allows progress handler to be specified
2336    * @param url
2337    * @param progress (null) or object implementing IProgressIndicator
2338    */
2339   public static void showUrl(final String url, final IProgressIndicator progress)
2340   {
2341     new Thread(new Runnable()
2342     {
2343       public void run()
2344       {
2345         try
2346         {
2347           if (progress!=null) {
2348             progress.setProgressBar("Opening "+url, this.hashCode());
2349           }
2350           jalview.util.BrowserLauncher.openURL(url);
2351         } catch (Exception ex)
2352         {
2353           JOptionPane
2354                   .showInternalMessageDialog(
2355                           Desktop.desktop,
2356                           "Unixers: Couldn't find default web browser."
2357                                   + "\nAdd the full path to your browser in Preferences.",
2358                           "Web browser not found",
2359                           JOptionPane.WARNING_MESSAGE);
2360
2361           ex.printStackTrace();
2362         }
2363         if (progress!=null) {
2364           progress.setProgressBar(null, this.hashCode());
2365         }
2366       }
2367     }).start();
2368   }
2369
2370   public static WsParamSetManager wsparamManager = null;
2371
2372   public static ParamManager getUserParameterStore()
2373   {
2374     if (wsparamManager == null)
2375     {
2376       wsparamManager = new WsParamSetManager();
2377     }
2378     return wsparamManager;
2379   }
2380
2381
2382 }