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