2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
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.
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.
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
21 import jalview.bin.Cache;
25 import java.awt.datatransfer.*;
26 import java.awt.dnd.*;
27 import java.awt.event.*;
28 import java.io.BufferedInputStream;
29 import java.io.BufferedOutputStream;
31 import java.io.FileOutputStream;
32 import java.io.InputStream;
33 import java.lang.reflect.Constructor;
35 import java.net.URLConnection;
36 import java.nio.channels.ReadableByteChannel;
40 import javax.swing.event.MenuEvent;
41 import javax.swing.event.MenuListener;
49 public class Desktop extends jalview.jbgui.GDesktop implements
50 DropTargetListener, ClipboardOwner, IProgressIndicator
53 public static Desktop instance;
55 // Need to decide if the Memory Usage is to be included in
56 // Next release or not.
57 public static MyDesktopPane desktop;
59 // public static JDesktopPane desktop;
61 static int openFrameCount = 0;
63 static final int xOffset = 30;
65 static final int yOffset = 30;
67 public static jalview.ws.Discoverer discoverer;
69 public static Object[] jalviewClipboard;
71 public static boolean internalCopy = false;
73 static int fileLoadingCount = 0;
76 * Creates a new Desktop object.
81 * A note to implementors. It is ESSENTIAL that any activities that might
82 * block are spawned off as threads rather than waited for during this
86 doVamsasClientCheck();
89 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
90 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
91 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
93 boolean showjconsole = jalview.bin.Cache.getDefault(
94 "SHOW_JAVA_CONSOLE", false);
95 desktop = new MyDesktopPane(selmemusage);
96 showMemusage.setSelected(selmemusage);
97 desktop.setBackground(Color.white);
98 getContentPane().setLayout(new BorderLayout());
99 getContentPane().add(desktop, BorderLayout.CENTER);
100 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
102 // This line prevents Windows Look&Feel resizing all new windows to maximum
103 // if previous window was maximised
104 desktop.setDesktopManager(new DefaultDesktopManager());
106 Rectangle dims = getLastKnownDimensions("");
113 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
114 setBounds((int) (screenSize.width - 900) / 2,
115 (int) (screenSize.height - 650) / 2, 900, 650);
117 jconsole = new Console(this);
118 // immediately output essential build information
119 System.out.println("Jalview Desktop "+jalview.bin.Cache.getProperty("VERSION")+"\n"
121 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")+"\n"
122 + "Java version: " + System.getProperty("java.version")
123 + "\n"+System.getProperty("os.arch") + " "
124 + System.getProperty("os.name") + " "
125 + System.getProperty("os.version"));
127 showConsole(showjconsole);
129 this.addWindowListener(new WindowAdapter()
131 public void windowClosing(WindowEvent evt)
137 this.addMouseListener(new MouseAdapter()
139 public void mousePressed(MouseEvent evt)
141 if (SwingUtilities.isRightMouseButton(evt))
143 showPasteMenu(evt.getX(), evt.getY());
148 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
149 // Spawn a thread that shows the splashscreen
150 SwingUtilities.invokeLater(new Runnable()
158 discoverer = new jalview.ws.Discoverer(); // Only gets started if gui is
160 // Thread off a new instance of the file chooser - this reduces the time it takes to open it later on.
161 new Thread(new Runnable() {
163 Cache.log.debug("Filechooser init thread started.");
164 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
165 .getProperty("LAST_DIRECTORY"),
166 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
167 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
168 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
169 Cache.log.debug("Filechooser init thread finished.");
175 * recover the last known dimensions for a jalview window
177 * - empty string is desktop, all other windows have unique prefix
178 * @return null or last known dimensions scaled to current geometry (if last
179 * window geom was known)
181 Rectangle getLastKnownDimensions(String windowName)
183 // TODO: lock aspect ratio for scaling desktop Bug #0058199
184 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
185 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
186 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
187 String width = jalview.bin.Cache.getProperty(windowName
189 String height = jalview.bin.Cache.getProperty(windowName
191 if ((x != null) && (y != null) && (width != null) && (height != null))
193 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
194 .parseInt(width), ih = Integer.parseInt(height);
195 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
197 // attempt #1 - try to cope with change in screen geometry - this
198 // version doesn't preserve original jv aspect ratio.
199 // take ratio of current screen size vs original screen size.
200 double sw = ( (1f*screenSize.width)
201 / (1f*Integer.parseInt(jalview.bin.Cache
202 .getProperty("SCREENGEOMETRY_WIDTH"))))
204 double sh = ( (1f*screenSize.height)
205 / (1f*Integer.parseInt(jalview.bin.Cache
206 .getProperty("SCREENGEOMETRY_HEIGHT"))));
207 // rescale the bounds depending upon the current screen geometry.
208 ix = (int) (ix * sw);
209 iw = (int) (iw * sw);
210 iy = (int) (iy * sh);
211 ih = (int) (ih * sh);
212 jalview.bin.Cache.log.debug("Got last known dimensions for "+windowName+": x:"+ix + " y:"+iy + " width:"+iw+" height:"+ih);
214 // return dimensions for new instance
215 return new Rectangle(ix, iy, iw, ih);
220 private void doVamsasClientCheck()
222 if (jalview.bin.Cache.vamsasJarsPresent())
224 setupVamsasDisconnectedGui();
225 VamsasMenu.setVisible(true);
226 final Desktop us = this;
227 VamsasMenu.addMenuListener(new MenuListener()
229 // this listener remembers when the menu was first selected, and
230 // doesn't rebuild the session list until it has been cleared and
232 boolean refresh = true;
234 public void menuCanceled(MenuEvent e)
239 public void menuDeselected(MenuEvent e)
244 public void menuSelected(MenuEvent e)
248 us.buildVamsasStMenu();
253 vamsasStart.setVisible(true);
257 void showPasteMenu(int x, int y)
259 JPopupMenu popup = new JPopupMenu();
260 JMenuItem item = new JMenuItem("Paste To New Window");
261 item.addActionListener(new ActionListener()
263 public void actionPerformed(ActionEvent evt)
270 popup.show(this, x, y);
277 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
278 Transferable contents = c.getContents(this);
280 if (contents != null)
282 String file = (String) contents
283 .getTransferData(DataFlavor.stringFlavor);
285 String format = new IdentifyFile().Identify(file,
286 FormatAdapter.PASTE);
288 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
291 } catch (Exception ex)
294 .println("Unable to paste alignment from system clipboard:\n"
300 * Adds and opens the given frame to the desktop
311 public static synchronized void addInternalFrame(
312 final JInternalFrame frame, String title, int w, int h)
314 addInternalFrame(frame, title, w, h, true);
331 public static synchronized void addInternalFrame(
332 final JInternalFrame frame, String title, int w, int h,
336 //TODO: allow callers to determine X and Y position of frame (eg. via bounds object).
337 // TODO: consider fixing method to update entries in the window submenu with
338 // the current window title
340 frame.setTitle(title);
341 if (frame.getWidth() < 1 || frame.getHeight() < 1)
345 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
346 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
347 // IF JALVIEW IS RUNNING HEADLESS
348 // ///////////////////////////////////////////////
349 if (System.getProperty("java.awt.headless") != null
350 && System.getProperty("java.awt.headless").equals("true"))
357 frame.setVisible(true);
358 frame.setClosable(true);
359 frame.setResizable(resizable);
360 frame.setMaximizable(resizable);
361 frame.setIconifiable(resizable);
362 frame.setFrameIcon(null);
364 if (frame.getX() < 1 && frame.getY() < 1)
366 frame.setLocation(xOffset * openFrameCount, yOffset
367 * ((openFrameCount - 1) % 10) + yOffset);
370 final JMenuItem menuItem = new JMenuItem(title);
372 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
374 public void internalFrameActivated(
375 javax.swing.event.InternalFrameEvent evt)
377 JInternalFrame itf = desktop.getSelectedFrame();
385 public void internalFrameClosed(
386 javax.swing.event.InternalFrameEvent evt)
388 PaintRefresher.RemoveComponent(frame);
390 windowMenu.remove(menuItem);
391 JInternalFrame itf = desktop.getSelectedFrame();
400 menuItem.addActionListener(new ActionListener()
402 public void actionPerformed(ActionEvent e)
406 frame.setSelected(true);
407 frame.setIcon(false);
408 } catch (java.beans.PropertyVetoException ex)
415 windowMenu.add(menuItem);
421 frame.setSelected(true);
422 frame.requestFocus();
423 } catch (java.beans.PropertyVetoException ve)
428 public void lostOwnership(Clipboard clipboard, Transferable contents)
432 Desktop.jalviewClipboard = null;
435 internalCopy = false;
438 public void dragEnter(DropTargetDragEvent evt)
442 public void dragExit(DropTargetEvent evt)
446 public void dragOver(DropTargetDragEvent evt)
450 public void dropActionChanged(DropTargetDragEvent evt)
460 public void drop(DropTargetDropEvent evt)
462 Transferable t = evt.getTransferable();
463 java.util.List files = null;
464 java.util.List protocols = null;
468 DataFlavor uriListFlavor = new DataFlavor(
469 "text/uri-list;class=java.lang.String");
470 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
472 // Works on Windows and MacOSX
473 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
474 files = (java.util.List) t
475 .getTransferData(DataFlavor.javaFileListFlavor);
477 else if (t.isDataFlavorSupported(uriListFlavor))
479 // This is used by Unix drag system
480 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
481 String data = (String) t.getTransferData(uriListFlavor);
482 files = new java.util.ArrayList(1);
483 protocols = new java.util.ArrayList(1);
484 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
485 data, "\r\n"); st.hasMoreTokens();)
487 String s = st.nextToken();
488 if (s.startsWith("#"))
490 // the line is a comment (as per the RFC 2483)
493 java.net.URI uri = new java.net.URI(s);
494 if (uri.getScheme().toLowerCase().startsWith("http"))
496 protocols.add(FormatAdapter.URL);
497 files.add(uri.toString());
501 // otherwise preserve old behaviour: catch all for file objects
502 java.io.File file = new java.io.File(uri);
503 protocols.add(FormatAdapter.FILE);
504 files.add(file.toString());
508 } catch (Exception e)
516 for (int i = 0; i < files.size(); i++)
518 String file = files.get(i).toString();
519 String protocol = (protocols == null) ? FormatAdapter.FILE
520 : (String) protocols.get(i);
521 String format = null;
523 if (file.endsWith(".jar"))
530 format = new IdentifyFile().Identify(file, protocol);
533 new FileLoader().LoadFile(file, protocol, format);
536 } catch (Exception ex)
548 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
550 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
551 .getProperty("LAST_DIRECTORY"),
552 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
553 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
554 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
556 chooser.setFileView(new JalviewFileView());
557 chooser.setDialogTitle("Open local file");
558 chooser.setToolTipText("Open");
560 int value = chooser.showOpenDialog(this);
562 if (value == JalviewFileChooser.APPROVE_OPTION)
564 String choice = chooser.getSelectedFile().getPath();
565 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
566 .getSelectedFile().getParent());
568 String format = null;
569 if (chooser.getSelectedFormat().equals("Jalview"))
575 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
578 if (viewport != null)
580 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
585 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
596 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
598 // This construct allows us to have a wider textfield
600 JLabel label = new JLabel("Enter URL of Input File");
601 final JComboBox history = new JComboBox();
603 JPanel panel = new JPanel(new GridLayout(2, 1));
606 history.setPreferredSize(new Dimension(400, 20));
607 history.setEditable(true);
608 history.addItem("http://www.");
610 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
614 if (historyItems != null)
616 st = new StringTokenizer(historyItems, "\t");
618 while (st.hasMoreTokens())
620 history.addItem(st.nextElement());
624 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
625 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
627 if (reply != JOptionPane.OK_OPTION)
632 String url = history.getSelectedItem().toString();
634 if (url.toLowerCase().endsWith(".jar"))
636 if (viewport != null)
638 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
643 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
648 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
650 if (format.equals("URL NOT FOUND"))
652 JOptionPane.showInternalMessageDialog(Desktop.desktop,
653 "Couldn't locate " + url, "URL not found",
654 JOptionPane.WARNING_MESSAGE);
659 if (viewport != null)
661 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
665 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
676 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
678 CutAndPasteTransfer cap = new CutAndPasteTransfer();
679 cap.setForInput(viewport);
680 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
688 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
690 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
691 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
693 storeLastKnownDimensions("",new Rectangle(getBounds().x,getBounds().y, getWidth(), getHeight()));
695 if (jconsole != null)
697 storeLastKnownDimensions("JAVA_CONSOLE_",jconsole.getBounds());
698 jconsole.stopConsole();
703 private void storeLastKnownDimensions(String string, Rectangle jc)
705 jalview.bin.Cache.log.debug("Storing last known dimensions for "+string+": x:"+jc.x + " y:"+jc.y + " width:"+jc.width+" height:"+jc.height);
707 jalview.bin.Cache.setProperty(string+"SCREEN_X",jc.x + "");
708 jalview.bin.Cache.setProperty(string+"SCREEN_Y", jc.y + "");
709 jalview.bin.Cache.setProperty(string+"SCREEN_WIDTH", jc.width + "");
710 jalview.bin.Cache.setProperty(string+"SCREEN_HEIGHT", jc.height
720 public void aboutMenuItem_actionPerformed(ActionEvent e)
722 StringBuffer message = new StringBuffer("Jalview version "
723 + jalview.bin.Cache.getProperty("VERSION") + "; last updated: "
724 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
726 if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
727 jalview.bin.Cache.getProperty("VERSION")))
730 .append("\n\n!! Jalview version "
731 + jalview.bin.Cache.getProperty("LATEST_VERSION")
732 + " is available for download from http://www.jalview.org !!\n");
735 // TODO: update this text for each release or centrally store it for lite
738 .append("\nAuthors: Andrew Waterhouse, Jim Procter, Michele Clamp, James Cuff, Steve Searle,\n David Martin & Geoff Barton."
739 + "\nDevelopment managed by The Barton Group, University of Dundee, Scotland, UK.\n"
740 + "\nFor help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list\n"
741 + "\nIf you use Jalview, please cite:"
742 + "\nWaterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
743 + "\nJalview Version 2 - a multiple sequence alignment editor and analysis workbench"
744 + "\nBioinformatics doi: 10.1093/bioinformatics/btp033");
745 JOptionPane.showInternalMessageDialog(Desktop.desktop,
747 message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
756 public void documentationMenuItem_actionPerformed(ActionEvent e)
760 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
761 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
762 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
764 javax.help.HelpBroker hb = hs.createHelpBroker();
765 hb.setCurrentID("home");
766 hb.setDisplayed(true);
767 } catch (Exception ex)
772 public void closeAll_actionPerformed(ActionEvent e)
774 JInternalFrame[] frames = desktop.getAllFrames();
775 for (int i = 0; i < frames.length; i++)
779 frames[i].setClosed(true);
780 } catch (java.beans.PropertyVetoException ex)
784 System.out.println("ALL CLOSED");
785 if (v_client != null)
787 // TODO clear binding to vamsas document objects on close_all
792 public void raiseRelated_actionPerformed(ActionEvent e)
794 reorderAssociatedWindows(false, false);
797 public void minimizeAssociated_actionPerformed(ActionEvent e)
799 reorderAssociatedWindows(true, false);
802 void closeAssociatedWindows()
804 reorderAssociatedWindows(false, true);
810 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
813 protected void garbageCollect_actionPerformed(ActionEvent e)
815 // We simply collect the garbage
816 jalview.bin.Cache.log.debug("Collecting garbage...");
818 jalview.bin.Cache.log.debug("Finished garbage collection.");
825 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
828 protected void showMemusage_actionPerformed(ActionEvent e)
830 desktop.showMemoryUsage(showMemusage.isSelected());
837 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
840 protected void showConsole_actionPerformed(ActionEvent e)
842 showConsole(showConsole.isSelected());
845 Console jconsole = null;
848 * control whether the java console is visible or not
852 void showConsole(boolean selected)
854 showConsole.setSelected(selected);
855 // TODO: decide if we should update properties file
856 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
858 jconsole.setVisible(selected);
861 void reorderAssociatedWindows(boolean minimize, boolean close)
863 JInternalFrame[] frames = desktop.getAllFrames();
864 if (frames == null || frames.length < 1)
869 AlignViewport source = null, target = null;
870 if (frames[0] instanceof AlignFrame)
872 source = ((AlignFrame) frames[0]).getCurrentView();
874 else if (frames[0] instanceof TreePanel)
876 source = ((TreePanel) frames[0]).getViewPort();
878 else if (frames[0] instanceof PCAPanel)
880 source = ((PCAPanel) frames[0]).av;
882 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
884 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
889 for (int i = 0; i < frames.length; i++)
892 if (frames[i] == null)
896 if (frames[i] instanceof AlignFrame)
898 target = ((AlignFrame) frames[i]).getCurrentView();
900 else if (frames[i] instanceof TreePanel)
902 target = ((TreePanel) frames[i]).getViewPort();
904 else if (frames[i] instanceof PCAPanel)
906 target = ((PCAPanel) frames[i]).av;
908 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
910 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
913 if (source == target)
919 frames[i].setClosed(true);
923 frames[i].setIcon(minimize);
930 } catch (java.beans.PropertyVetoException ex)
944 protected void preferences_actionPerformed(ActionEvent e)
955 public void saveState_actionPerformed(ActionEvent e)
957 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
958 .getProperty("LAST_DIRECTORY"), new String[]
959 { "jar" }, new String[]
960 { "Jalview Project" }, "Jalview Project");
962 chooser.setFileView(new JalviewFileView());
963 chooser.setDialogTitle("Save State");
965 int value = chooser.showSaveDialog(this);
967 if (value == JalviewFileChooser.APPROVE_OPTION)
969 java.io.File choice = chooser.getSelectedFile();
970 JProgressBar progpanel = addProgressPanel("Saving jalview project "
972 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
973 // TODO catch and handle errors for savestate
974 new Jalview2XML().SaveState(choice);
975 removeProgressPanel(progpanel);
986 public void loadState_actionPerformed(ActionEvent e)
988 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
989 .getProperty("LAST_DIRECTORY"), new String[]
990 { "jar" }, new String[]
991 { "Jalview Project" }, "Jalview Project");
992 chooser.setFileView(new JalviewFileView());
993 chooser.setDialogTitle("Restore state");
995 int value = chooser.showOpenDialog(this);
997 if (value == JalviewFileChooser.APPROVE_OPTION)
999 String choice = chooser.getSelectedFile().getAbsolutePath();
1000 setProgressBar("loading jalview project "
1001 + chooser.getSelectedFile().getName(), choice.hashCode());
1002 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1003 .getSelectedFile().getParent());
1004 new Jalview2XML().LoadJalviewAlign(choice);
1005 setProgressBar(null, choice.hashCode());
1009 public void inputSequence_actionPerformed(ActionEvent e)
1011 new SequenceFetcher(this);
1014 JPanel progressPanel;
1016 public void startLoading(final String fileName)
1018 if (fileLoadingCount == 0)
1020 addProgressPanel("Loading File: " + fileName + " ");
1026 private JProgressBar addProgressPanel(String string)
1028 if (progressPanel == null)
1030 progressPanel = new JPanel(new BorderLayout());
1031 totalProgressCount = 0;
1033 JProgressBar progressBar = new JProgressBar();
1034 progressBar.setIndeterminate(true);
1036 progressPanel.add(new JLabel(string), BorderLayout.WEST);
1038 progressPanel.add(progressBar, BorderLayout.CENTER);
1040 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1041 totalProgressCount++;
1046 int totalProgressCount = 0;
1048 private void removeProgressPanel(JProgressBar progbar)
1050 if (progressPanel != null)
1052 progressPanel.remove(progbar);
1053 if (--totalProgressCount < 1)
1055 this.getContentPane().remove(progressPanel);
1056 progressPanel = null;
1062 public void stopLoading()
1065 if (fileLoadingCount < 1)
1067 if (progressPanel != null)
1069 this.getContentPane().remove(progressPanel);
1070 progressPanel = null;
1072 fileLoadingCount = 0;
1077 public static int getViewCount(String viewId)
1079 AlignViewport[] aps = getViewports(viewId);
1080 return (aps == null) ? 0 : aps.length;
1086 * @return all AlignmentPanels concerning the viewId sequence set
1088 public static AlignmentPanel[] getAlignmentPanels(String viewId)
1091 if (Desktop.desktop == null)
1093 // no frames created and in headless mode
1094 // TODO: verify that frames are recoverable when in headless mode
1097 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1098 ArrayList aps = new ArrayList();
1099 for (int t = 0; t < frames.length; t++)
1101 if (frames[t] instanceof AlignFrame)
1103 AlignFrame af = (AlignFrame) frames[t];
1104 for (int a = 0; a < af.alignPanels.size(); a++)
1107 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1108 .getSequenceSetId()))
1110 aps.add(af.alignPanels.elementAt(a));
1115 if (aps.size() == 0)
1119 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1120 for (int t = 0; t < vap.length; t++)
1122 vap[t] = (AlignmentPanel) aps.get(t);
1128 * get all the viewports on an alignment.
1130 * @param sequenceSetId
1131 * unique alignment id
1132 * @return all viewports on the alignment bound to sequenceSetId
1134 public static AlignViewport[] getViewports(String sequenceSetId)
1136 Vector viewp = new Vector();
1137 if (desktop != null)
1139 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1141 for (int t = 0; t < frames.length; t++)
1143 if (frames[t] instanceof AlignFrame)
1145 AlignFrame afr = ((AlignFrame) frames[t]);
1146 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1148 if (afr.alignPanels != null)
1150 for (int a = 0; a < afr.alignPanels.size(); a++)
1152 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1153 .elementAt(a)).av.getSequenceSetId()))
1155 viewp.addElement(((AlignmentPanel) afr.alignPanels
1162 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1167 if (viewp.size() > 0)
1169 AlignViewport[] vp = new AlignViewport[viewp.size()];
1177 public void explodeViews(AlignFrame af)
1179 int size = af.alignPanels.size();
1185 for (int i = 0; i < size; i++)
1187 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1188 AlignFrame newaf = new AlignFrame(ap);
1189 if (ap.av.explodedPosition != null
1190 && !ap.av.explodedPosition.equals(af.getBounds()))
1192 newaf.setBounds(ap.av.explodedPosition);
1195 ap.av.gatherViewsHere = false;
1197 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1198 AlignFrame.DEFAULT_HEIGHT);
1201 af.alignPanels.clear();
1202 af.closeMenuItem_actionPerformed(true);
1206 public void gatherViews(AlignFrame source)
1208 source.viewport.gatherViewsHere = true;
1209 source.viewport.explodedPosition = source.getBounds();
1210 JInternalFrame[] frames = desktop.getAllFrames();
1211 String viewId = source.viewport.sequenceSetID;
1213 for (int t = 0; t < frames.length; t++)
1215 if (frames[t] instanceof AlignFrame && frames[t] != source)
1217 AlignFrame af = (AlignFrame) frames[t];
1218 boolean gatherThis = false;
1219 for (int a = 0; a < af.alignPanels.size(); a++)
1221 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1222 if (viewId.equals(ap.av.getSequenceSetId()))
1225 ap.av.gatherViewsHere = false;
1226 ap.av.explodedPosition = af.getBounds();
1227 source.addAlignmentPanel(ap, false);
1233 af.alignPanels.clear();
1234 af.closeMenuItem_actionPerformed(true);
1241 jalview.gui.VamsasApplication v_client = null;
1243 public void vamsasImport_actionPerformed(ActionEvent e)
1245 if (v_client == null)
1247 // Load and try to start a session.
1248 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1249 .getProperty("LAST_DIRECTORY"));
1251 chooser.setFileView(new JalviewFileView());
1252 chooser.setDialogTitle("Open a saved VAMSAS session");
1254 .setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1256 int value = chooser.showOpenDialog(this);
1258 if (value == JalviewFileChooser.APPROVE_OPTION)
1260 String fle = chooser.getSelectedFile().toString();
1261 if (!vamsasImport(chooser.getSelectedFile()))
1263 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1264 "Couldn't import '" + fle + "' as a new vamsas session.",
1265 "Vamsas Document Import Failed",
1266 JOptionPane.ERROR_MESSAGE);
1272 jalview.bin.Cache.log
1273 .error("Implementation error - load session from a running session is not supported.");
1278 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1281 * @return true if import was a success and a session was started.
1283 public boolean vamsasImport(URL url)
1285 // TODO: create progress bar
1286 if (v_client != null)
1289 jalview.bin.Cache.log
1290 .error("Implementation error - load session from a running session is not supported.");
1296 // copy the URL content to a temporary local file
1297 // TODO: be a bit cleverer here with nio (?!)
1298 File file = File.createTempFile("vdocfromurl", ".vdj");
1299 FileOutputStream fos = new FileOutputStream(file);
1300 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1301 byte[] buffer = new byte[2048];
1303 while ((ln = bis.read(buffer)) > -1)
1305 fos.write(buffer, 0, ln);
1309 v_client = new jalview.gui.VamsasApplication(this, file, url
1311 } catch (Exception ex)
1313 jalview.bin.Cache.log.error(
1314 "Failed to create new vamsas session from contents of URL "
1318 setupVamsasConnectedGui();
1319 v_client.initial_update(); // TODO: thread ?
1320 return v_client.inSession();
1324 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1327 * @return true if import was a success and a session was started.
1329 public boolean vamsasImport(File file)
1331 if (v_client != null)
1334 jalview.bin.Cache.log
1335 .error("Implementation error - load session from a running session is not supported.");
1339 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1343 v_client = new jalview.gui.VamsasApplication(this, file, null);
1344 } catch (Exception ex)
1346 setProgressBar("Importing VAMSAS session from " + file.getName(),
1348 jalview.bin.Cache.log.error(
1349 "New vamsas session from existing session file failed:", ex);
1352 setupVamsasConnectedGui();
1353 v_client.initial_update(); // TODO: thread ?
1354 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1356 return v_client.inSession();
1359 public boolean joinVamsasSession(String mysesid)
1361 if (v_client != null)
1364 "Trying to join a vamsas session when another is already connected.");
1366 if (mysesid == null)
1368 throw new Error("Invalid vamsas session id.");
1370 v_client = new VamsasApplication(this, mysesid);
1371 setupVamsasConnectedGui();
1372 v_client.initial_update();
1373 return (v_client.inSession());
1376 public void vamsasStart_actionPerformed(ActionEvent e)
1378 if (v_client == null)
1381 // we just start a default session for moment.
1383 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1384 * getProperty("LAST_DIRECTORY"));
1386 * chooser.setFileView(new JalviewFileView());
1387 * chooser.setDialogTitle("Load Vamsas file");
1388 * chooser.setToolTipText("Import");
1390 * int value = chooser.showOpenDialog(this);
1392 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1393 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1395 v_client = new VamsasApplication(this);
1396 setupVamsasConnectedGui();
1397 v_client.initial_update(); // TODO: thread ?
1401 // store current data in session.
1402 v_client.push_update(); // TODO: thread
1406 protected void setupVamsasConnectedGui()
1408 vamsasStart.setText("Session Update");
1409 vamsasSave.setVisible(true);
1410 vamsasStop.setVisible(true);
1411 vamsasImport.setVisible(false); // Document import to existing session is
1412 // not possible for vamsas-client-1.0.
1415 protected void setupVamsasDisconnectedGui()
1417 vamsasSave.setVisible(false);
1418 vamsasStop.setVisible(false);
1419 vamsasImport.setVisible(true);
1420 vamsasStart.setText("New Vamsas Session");
1423 public void vamsasStop_actionPerformed(ActionEvent e)
1425 if (v_client != null)
1427 v_client.end_session();
1429 setupVamsasDisconnectedGui();
1433 protected void buildVamsasStMenu()
1435 if (v_client == null)
1437 String[] sess = null;
1440 sess = VamsasApplication.getSessionList();
1441 } catch (Exception e)
1443 jalview.bin.Cache.log.warn(
1444 "Problem getting current sessions list.", e);
1449 jalview.bin.Cache.log.debug("Got current sessions list: "
1450 + sess.length + " entries.");
1451 VamsasStMenu.removeAll();
1452 for (int i = 0; i < sess.length; i++)
1454 JMenuItem sessit = new JMenuItem();
1455 sessit.setText(sess[i]);
1456 sessit.setToolTipText("Connect to session " + sess[i]);
1457 final Desktop dsktp = this;
1458 final String mysesid = sess[i];
1459 sessit.addActionListener(new ActionListener()
1462 public void actionPerformed(ActionEvent e)
1464 if (dsktp.v_client == null)
1466 Thread rthr = new Thread(new Runnable()
1471 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1472 dsktp.setupVamsasConnectedGui();
1473 dsktp.v_client.initial_update();
1481 VamsasStMenu.add(sessit);
1483 // don't show an empty menu.
1484 VamsasStMenu.setVisible(sess.length > 0);
1489 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1490 VamsasStMenu.removeAll();
1491 VamsasStMenu.setVisible(false);
1496 // Not interested in the content. Just hide ourselves.
1497 VamsasStMenu.setVisible(false);
1501 public void vamsasSave_actionPerformed(ActionEvent e)
1503 if (v_client != null)
1505 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1506 .getProperty("LAST_DIRECTORY"), new String[]
1507 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1509 { "Vamsas Document" }, "Vamsas Document");
1511 chooser.setFileView(new JalviewFileView());
1512 chooser.setDialogTitle("Save Vamsas Document Archive");
1514 int value = chooser.showSaveDialog(this);
1516 if (value == JalviewFileChooser.APPROVE_OPTION)
1518 java.io.File choice = chooser.getSelectedFile();
1519 JProgressBar progpanel = addProgressPanel("Saving VAMSAS Document to "
1520 + choice.getName());
1521 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1522 String warnmsg = null;
1523 String warnttl = null;
1526 v_client.vclient.storeDocument(choice);
1529 warnttl = "Serious Problem saving Vamsas Document";
1530 warnmsg = ex.toString();
1531 jalview.bin.Cache.log.error("Error Whilst saving document to "
1534 } catch (Exception ex)
1536 warnttl = "Problem saving Vamsas Document.";
1537 warnmsg = ex.toString();
1538 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1542 removeProgressPanel(progpanel);
1543 if (warnmsg != null)
1545 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1547 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1553 JProgressBar vamUpdate = null;
1556 * hide vamsas user gui bits when a vamsas document event is being handled.
1559 * true to hide gui, false to reveal gui
1561 public void setVamsasUpdate(boolean b)
1563 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
1564 + (b ? "in progress" : "finished"));
1566 if (vamUpdate != null)
1568 this.removeProgressPanel(vamUpdate);
1572 vamUpdate = this.addProgressPanel("Updating vamsas session");
1574 vamsasStart.setVisible(!b);
1575 vamsasStop.setVisible(!b);
1576 vamsasSave.setVisible(!b);
1579 public JInternalFrame[] getAllFrames()
1581 return desktop.getAllFrames();
1585 * Checks the given url to see if it gives a response indicating that the user
1586 * should be informed of a new questionnaire.
1590 public void checkForQuestionnaire(String url)
1592 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
1593 // javax.swing.SwingUtilities.invokeLater(jvq);
1594 new Thread(jvq).start();
1598 * Proxy class for JDesktopPane which optionally displays the current memory
1599 * usage and highlights the desktop area with a red bar if free memory runs
1604 public class MyDesktopPane extends JDesktopPane implements Runnable
1607 boolean showMemoryUsage = false;
1611 java.text.NumberFormat df;
1613 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
1616 public MyDesktopPane(boolean showMemoryUsage)
1618 showMemoryUsage(showMemoryUsage);
1621 public void showMemoryUsage(boolean showMemoryUsage)
1623 this.showMemoryUsage = showMemoryUsage;
1624 if (showMemoryUsage)
1626 Thread worker = new Thread(this);
1631 public boolean isShowMemoryUsage()
1633 return showMemoryUsage;
1638 df = java.text.NumberFormat.getNumberInstance();
1639 df.setMaximumFractionDigits(2);
1640 runtime = Runtime.getRuntime();
1642 while (showMemoryUsage)
1646 maxMemory = runtime.maxMemory() / 1048576f;
1647 allocatedMemory = runtime.totalMemory() / 1048576f;
1648 freeMemory = runtime.freeMemory() / 1048576f;
1649 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
1651 percentUsage = (totalFreeMemory / maxMemory) * 100;
1653 // if (percentUsage < 20)
1655 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
1657 // instance.set.setBorder(border1);
1660 // sleep after showing usage
1662 } catch (Exception ex)
1664 ex.printStackTrace();
1669 public void paintComponent(Graphics g)
1671 if (showMemoryUsage && g != null)
1673 if (percentUsage < 20)
1674 g.setColor(Color.red);
1675 FontMetrics fm = g.getFontMetrics();
1677 { g.drawString("Total Free Memory: " + df.format(totalFreeMemory)
1678 + "MB; Max Memory: " + df.format(maxMemory) + "MB; "
1679 + df.format(percentUsage) + "%", 10, getHeight()
1687 protected JMenuItem groovyShell;
1689 public void doGroovyCheck()
1691 if (jalview.bin.Cache.groovyJarsPresent())
1693 groovyShell = new JMenuItem();
1694 groovyShell.setText("Groovy Console...");
1695 groovyShell.addActionListener(new ActionListener()
1697 public void actionPerformed(ActionEvent e)
1699 groovyShell_actionPerformed(e);
1702 toolsMenu.add(groovyShell);
1703 groovyShell.setVisible(true);
1708 * Accessor method to quickly get all the AlignmentFrames loaded.
1710 public static AlignFrame[] getAlignframes()
1712 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1718 Vector avp = new Vector();
1722 for (int i = frames.length - 1; i > -1; i--)
1724 if (frames[i] instanceof AlignFrame)
1726 AlignFrame af = (AlignFrame) frames[i];
1730 } catch (Exception ex)
1732 ex.printStackTrace();
1734 if (avp.size() == 0)
1738 AlignFrame afs[] = new AlignFrame[avp.size()];
1739 for (int i = 0, j = avp.size(); i < j; i++)
1741 afs[i] = (AlignFrame) avp.elementAt(i);
1748 * Add Groovy Support to Jalview
1750 public void groovyShell_actionPerformed(ActionEvent e)
1752 // use reflection to avoid creating compilation dependency.
1753 if (!jalview.bin.Cache.groovyJarsPresent())
1756 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
1760 Class gcClass = Desktop.class.getClassLoader().loadClass(
1761 "groovy.ui.Console");
1762 Constructor gccons = gcClass.getConstructor(null);
1763 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
1765 { String.class, Object.class });
1766 java.lang.reflect.Method run = gcClass.getMethod("run", null);
1767 Object gc = gccons.newInstance(null);
1768 setvar.invoke(gc, new Object[]
1769 { "Jalview", this });
1770 run.invoke(gc, null);
1771 } catch (Exception ex)
1773 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
1775 .showInternalMessageDialog(
1778 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
1779 "Jalview Groovy Support Failed",
1780 JOptionPane.ERROR_MESSAGE);
1785 * Progress bars managed by the IProgressIndicator method.
1787 private Hashtable progressBars, progressBarHandlers;
1792 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
1794 public void setProgressBar(String message, long id)
1796 if (progressBars == null)
1798 progressBars = new Hashtable();
1799 progressBarHandlers = new Hashtable();
1802 if (progressBars.get(new Long(id)) != null)
1804 JProgressBar progressPanel = (JProgressBar) progressBars
1805 .remove(new Long(id));
1806 if (progressBarHandlers.contains(new Long(id)))
1808 progressBarHandlers.remove(new Long(id));
1810 removeProgressPanel(progressPanel);
1814 progressBars.put(new Long(id), addProgressPanel(message));
1821 * @see jalview.gui.IProgressIndicator#registerHandler(long,
1822 * jalview.gui.IProgressIndicatorHandler)
1824 public void registerHandler(final long id,
1825 final IProgressIndicatorHandler handler)
1827 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
1830 "call setProgressBar before registering the progress bar's handler.");
1832 progressBarHandlers.put(new Long(id), handler);
1833 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
1834 if (handler.canCancel())
1836 JButton cancel = new JButton("Cancel");
1837 final IProgressIndicator us = this;
1838 cancel.addActionListener(new ActionListener()
1841 public void actionPerformed(ActionEvent e)
1843 handler.cancelActivity(id);
1844 us.setProgressBar("Cancelled "
1845 + ((JLabel) progressPanel.getComponent(0)).getText(), id);
1848 progressPanel.add(cancel, BorderLayout.EAST);
1853 * This will return the first AlignFrame viewing AlignViewport av. It will
1854 * break if there are more than one AlignFrames viewing a particular av. This
1857 * @return alignFrame for av
1859 public static AlignFrame getAlignFrameFor(AlignViewport av)
1861 if (desktop != null)
1863 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
1864 for (int panel = 0; aps != null && panel < aps.length; panel++)
1866 if (aps[panel] != null && aps[panel].av == av)
1868 return aps[panel].alignFrame;
1875 public VamsasApplication getVamsasApplication()