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