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