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
163 * recover the last known dimensions for a jalview window
165 * - empty string is desktop, all other windows have unique prefix
166 * @return null or last known dimensions scaled to current geometry (if last
167 * window geom was known)
169 Rectangle getLastKnownDimensions(String windowName)
171 // TODO: lock aspect ratio for scaling desktop Bug #0058199
172 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
173 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
174 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
175 String width = jalview.bin.Cache.getProperty(windowName
177 String height = jalview.bin.Cache.getProperty(windowName
179 if ((x != null) && (y != null) && (width != null) && (height != null))
181 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
182 .parseInt(width), ih = Integer.parseInt(height);
183 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
185 // attempt #1 - try to cope with change in screen geometry - this
186 // version doesn't preserve original jv aspect ratio.
187 // take ratio of current screen size vs original screen size.
188 double sw = ( (1f*screenSize.width)
189 / (1f*Integer.parseInt(jalview.bin.Cache
190 .getProperty("SCREENGEOMETRY_WIDTH"))))
192 double sh = ( (1f*screenSize.height)
193 / (1f*Integer.parseInt(jalview.bin.Cache
194 .getProperty("SCREENGEOMETRY_HEIGHT"))));
195 // rescale the bounds depending upon the current screen geometry.
196 ix = (int) (ix * sw);
197 iw = (int) (iw * sw);
198 iy = (int) (iy * sh);
199 ih = (int) (ih * sh);
200 jalview.bin.Cache.log.debug("Got last known dimensions for "+windowName+": x:"+ix + " y:"+iy + " width:"+iw+" height:"+ih);
202 // return dimensions for new instance
203 return new Rectangle(ix, iy, iw, ih);
208 private void doVamsasClientCheck()
210 if (jalview.bin.Cache.vamsasJarsPresent())
212 setupVamsasDisconnectedGui();
213 VamsasMenu.setVisible(true);
214 final Desktop us = this;
215 VamsasMenu.addMenuListener(new MenuListener()
217 // this listener remembers when the menu was first selected, and
218 // doesn't rebuild the session list until it has been cleared and
220 boolean refresh = true;
222 public void menuCanceled(MenuEvent e)
227 public void menuDeselected(MenuEvent e)
232 public void menuSelected(MenuEvent e)
236 us.buildVamsasStMenu();
241 vamsasStart.setVisible(true);
245 void showPasteMenu(int x, int y)
247 JPopupMenu popup = new JPopupMenu();
248 JMenuItem item = new JMenuItem("Paste To New Window");
249 item.addActionListener(new ActionListener()
251 public void actionPerformed(ActionEvent evt)
258 popup.show(this, x, y);
265 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
266 Transferable contents = c.getContents(this);
268 if (contents != null)
270 String file = (String) contents
271 .getTransferData(DataFlavor.stringFlavor);
273 String format = new IdentifyFile().Identify(file,
274 FormatAdapter.PASTE);
276 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
279 } catch (Exception ex)
282 .println("Unable to paste alignment from system clipboard:\n"
288 * Adds and opens the given frame to the desktop
299 public static synchronized void addInternalFrame(
300 final JInternalFrame frame, String title, int w, int h)
302 addInternalFrame(frame, title, w, h, true);
319 public static synchronized void addInternalFrame(
320 final JInternalFrame frame, String title, int w, int h,
324 //TODO: allow callers to determine X and Y position of frame (eg. via bounds object).
325 // TODO: consider fixing method to update entries in the window submenu with
326 // the current window title
328 frame.setTitle(title);
329 if (frame.getWidth() < 1 || frame.getHeight() < 1)
333 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
334 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
335 // IF JALVIEW IS RUNNING HEADLESS
336 // ///////////////////////////////////////////////
337 if (System.getProperty("java.awt.headless") != null
338 && System.getProperty("java.awt.headless").equals("true"))
345 frame.setVisible(true);
346 frame.setClosable(true);
347 frame.setResizable(resizable);
348 frame.setMaximizable(resizable);
349 frame.setIconifiable(resizable);
350 frame.setFrameIcon(null);
352 if (frame.getX() < 1 && frame.getY() < 1)
354 frame.setLocation(xOffset * openFrameCount, yOffset
355 * ((openFrameCount - 1) % 10) + yOffset);
358 final JMenuItem menuItem = new JMenuItem(title);
360 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
362 public void internalFrameActivated(
363 javax.swing.event.InternalFrameEvent evt)
365 JInternalFrame itf = desktop.getSelectedFrame();
373 public void internalFrameClosed(
374 javax.swing.event.InternalFrameEvent evt)
376 PaintRefresher.RemoveComponent(frame);
378 windowMenu.remove(menuItem);
379 JInternalFrame itf = desktop.getSelectedFrame();
388 menuItem.addActionListener(new ActionListener()
390 public void actionPerformed(ActionEvent e)
394 frame.setSelected(true);
395 frame.setIcon(false);
396 } catch (java.beans.PropertyVetoException ex)
403 windowMenu.add(menuItem);
409 frame.setSelected(true);
410 frame.requestFocus();
411 } catch (java.beans.PropertyVetoException ve)
416 public void lostOwnership(Clipboard clipboard, Transferable contents)
420 Desktop.jalviewClipboard = null;
423 internalCopy = false;
426 public void dragEnter(DropTargetDragEvent evt)
430 public void dragExit(DropTargetEvent evt)
434 public void dragOver(DropTargetDragEvent evt)
438 public void dropActionChanged(DropTargetDragEvent evt)
448 public void drop(DropTargetDropEvent evt)
450 Transferable t = evt.getTransferable();
451 java.util.List files = null;
452 java.util.List protocols = null;
456 DataFlavor uriListFlavor = new DataFlavor(
457 "text/uri-list;class=java.lang.String");
458 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
460 // Works on Windows and MacOSX
461 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
462 files = (java.util.List) t
463 .getTransferData(DataFlavor.javaFileListFlavor);
465 else if (t.isDataFlavorSupported(uriListFlavor))
467 // This is used by Unix drag system
468 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
469 String data = (String) t.getTransferData(uriListFlavor);
470 files = new java.util.ArrayList(1);
471 protocols = new java.util.ArrayList(1);
472 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
473 data, "\r\n"); st.hasMoreTokens();)
475 String s = st.nextToken();
476 if (s.startsWith("#"))
478 // the line is a comment (as per the RFC 2483)
481 java.net.URI uri = new java.net.URI(s);
482 if (uri.getScheme().toLowerCase().startsWith("http"))
484 protocols.add(FormatAdapter.URL);
485 files.add(uri.toString());
489 // otherwise preserve old behaviour: catch all for file objects
490 java.io.File file = new java.io.File(uri);
491 protocols.add(FormatAdapter.FILE);
492 files.add(file.toString());
496 } catch (Exception e)
504 for (int i = 0; i < files.size(); i++)
506 String file = files.get(i).toString();
507 String protocol = (protocols == null) ? FormatAdapter.FILE
508 : (String) protocols.get(i);
509 String format = null;
511 if (file.endsWith(".jar"))
518 format = new IdentifyFile().Identify(file, protocol);
521 new FileLoader().LoadFile(file, protocol, format);
524 } catch (Exception ex)
536 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
538 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
539 .getProperty("LAST_DIRECTORY"),
540 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
541 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
542 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
544 chooser.setFileView(new JalviewFileView());
545 chooser.setDialogTitle("Open local file");
546 chooser.setToolTipText("Open");
548 int value = chooser.showOpenDialog(this);
550 if (value == JalviewFileChooser.APPROVE_OPTION)
552 String choice = chooser.getSelectedFile().getPath();
553 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
554 .getSelectedFile().getParent());
556 String format = null;
557 if (chooser.getSelectedFormat().equals("Jalview"))
563 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
566 if (viewport != null)
568 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
573 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
584 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
586 // This construct allows us to have a wider textfield
588 JLabel label = new JLabel("Enter URL of Input File");
589 final JComboBox history = new JComboBox();
591 JPanel panel = new JPanel(new GridLayout(2, 1));
594 history.setPreferredSize(new Dimension(400, 20));
595 history.setEditable(true);
596 history.addItem("http://www.");
598 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
602 if (historyItems != null)
604 st = new StringTokenizer(historyItems, "\t");
606 while (st.hasMoreTokens())
608 history.addItem(st.nextElement());
612 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
613 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
615 if (reply != JOptionPane.OK_OPTION)
620 String url = history.getSelectedItem().toString();
622 if (url.toLowerCase().endsWith(".jar"))
624 if (viewport != null)
626 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
631 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
636 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
638 if (format.equals("URL NOT FOUND"))
640 JOptionPane.showInternalMessageDialog(Desktop.desktop,
641 "Couldn't locate " + url, "URL not found",
642 JOptionPane.WARNING_MESSAGE);
647 if (viewport != null)
649 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
653 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
664 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
666 CutAndPasteTransfer cap = new CutAndPasteTransfer();
667 cap.setForInput(viewport);
668 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
676 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
678 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
679 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
681 storeLastKnownDimensions("",new Rectangle(getBounds().x,getBounds().y, getWidth(), getHeight()));
683 if (jconsole != null)
685 storeLastKnownDimensions("JAVA_CONSOLE_",jconsole.getBounds());
686 jconsole.stopConsole();
691 private void storeLastKnownDimensions(String string, Rectangle jc)
693 jalview.bin.Cache.log.debug("Storing last known dimensions for "+string+": x:"+jc.x + " y:"+jc.y + " width:"+jc.width+" height:"+jc.height);
695 jalview.bin.Cache.setProperty(string+"SCREEN_X",jc.x + "");
696 jalview.bin.Cache.setProperty(string+"SCREEN_Y", jc.y + "");
697 jalview.bin.Cache.setProperty(string+"SCREEN_WIDTH", jc.width + "");
698 jalview.bin.Cache.setProperty(string+"SCREEN_HEIGHT", jc.height
708 public void aboutMenuItem_actionPerformed(ActionEvent e)
710 StringBuffer message = new StringBuffer("Jalview version "
711 + jalview.bin.Cache.getProperty("VERSION") + "; last updated: "
712 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
714 if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
715 jalview.bin.Cache.getProperty("VERSION")))
718 .append("\n\n!! Jalview version "
719 + jalview.bin.Cache.getProperty("LATEST_VERSION")
720 + " is available for download from http://www.jalview.org !!\n");
723 // TODO: update this text for each release or centrally store it for lite
726 .append("\nAuthors: Andrew Waterhouse, Jim Procter, Michele Clamp, James Cuff, Steve Searle,\n David Martin & Geoff Barton."
727 + "\nDevelopment managed by The Barton Group, University of Dundee, Scotland, UK.\n"
728 + "\nFor help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list\n"
729 + "\nIf you use Jalview, please cite:"
730 + "\nWaterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
731 + "\nJalview Version 2 - a multiple sequence alignment editor and analysis workbench"
732 + "\nBioinformatics doi: 10.1093/bioinformatics/btp033");
733 JOptionPane.showInternalMessageDialog(Desktop.desktop,
735 message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
744 public void documentationMenuItem_actionPerformed(ActionEvent e)
748 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
749 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
750 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
752 javax.help.HelpBroker hb = hs.createHelpBroker();
753 hb.setCurrentID("home");
754 hb.setDisplayed(true);
755 } catch (Exception ex)
760 public void closeAll_actionPerformed(ActionEvent e)
762 JInternalFrame[] frames = desktop.getAllFrames();
763 for (int i = 0; i < frames.length; i++)
767 frames[i].setClosed(true);
768 } catch (java.beans.PropertyVetoException ex)
772 System.out.println("ALL CLOSED");
773 if (v_client != null)
775 // TODO clear binding to vamsas document objects on close_all
780 public void raiseRelated_actionPerformed(ActionEvent e)
782 reorderAssociatedWindows(false, false);
785 public void minimizeAssociated_actionPerformed(ActionEvent e)
787 reorderAssociatedWindows(true, false);
790 void closeAssociatedWindows()
792 reorderAssociatedWindows(false, true);
798 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
801 protected void garbageCollect_actionPerformed(ActionEvent e)
803 // We simply collect the garbage
804 jalview.bin.Cache.log.debug("Collecting garbage...");
806 jalview.bin.Cache.log.debug("Finished garbage collection.");
813 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
816 protected void showMemusage_actionPerformed(ActionEvent e)
818 desktop.showMemoryUsage(showMemusage.isSelected());
825 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
828 protected void showConsole_actionPerformed(ActionEvent e)
830 showConsole(showConsole.isSelected());
833 Console jconsole = null;
836 * control whether the java console is visible or not
840 void showConsole(boolean selected)
842 showConsole.setSelected(selected);
843 // TODO: decide if we should update properties file
844 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
846 jconsole.setVisible(selected);
849 void reorderAssociatedWindows(boolean minimize, boolean close)
851 JInternalFrame[] frames = desktop.getAllFrames();
852 if (frames == null || frames.length < 1)
857 AlignViewport source = null, target = null;
858 if (frames[0] instanceof AlignFrame)
860 source = ((AlignFrame) frames[0]).getCurrentView();
862 else if (frames[0] instanceof TreePanel)
864 source = ((TreePanel) frames[0]).getViewPort();
866 else if (frames[0] instanceof PCAPanel)
868 source = ((PCAPanel) frames[0]).av;
870 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
872 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
877 for (int i = 0; i < frames.length; i++)
880 if (frames[i] == null)
884 if (frames[i] instanceof AlignFrame)
886 target = ((AlignFrame) frames[i]).getCurrentView();
888 else if (frames[i] instanceof TreePanel)
890 target = ((TreePanel) frames[i]).getViewPort();
892 else if (frames[i] instanceof PCAPanel)
894 target = ((PCAPanel) frames[i]).av;
896 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
898 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
901 if (source == target)
907 frames[i].setClosed(true);
911 frames[i].setIcon(minimize);
918 } catch (java.beans.PropertyVetoException ex)
932 protected void preferences_actionPerformed(ActionEvent e)
943 public void saveState_actionPerformed(ActionEvent e)
945 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
946 .getProperty("LAST_DIRECTORY"), new String[]
947 { "jar" }, new String[]
948 { "Jalview Project" }, "Jalview Project");
950 chooser.setFileView(new JalviewFileView());
951 chooser.setDialogTitle("Save State");
953 int value = chooser.showSaveDialog(this);
955 if (value == JalviewFileChooser.APPROVE_OPTION)
957 java.io.File choice = chooser.getSelectedFile();
958 JProgressBar progpanel = addProgressPanel("Saving jalview project "
960 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
961 // TODO catch and handle errors for savestate
962 new Jalview2XML().SaveState(choice);
963 removeProgressPanel(progpanel);
974 public void loadState_actionPerformed(ActionEvent e)
976 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
977 .getProperty("LAST_DIRECTORY"), new String[]
978 { "jar" }, new String[]
979 { "Jalview Project" }, "Jalview Project");
980 chooser.setFileView(new JalviewFileView());
981 chooser.setDialogTitle("Restore state");
983 int value = chooser.showOpenDialog(this);
985 if (value == JalviewFileChooser.APPROVE_OPTION)
987 String choice = chooser.getSelectedFile().getAbsolutePath();
988 setProgressBar("loading jalview project "
989 + chooser.getSelectedFile().getName(), choice.hashCode());
990 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
991 .getSelectedFile().getParent());
992 new Jalview2XML().LoadJalviewAlign(choice);
993 setProgressBar(null, choice.hashCode());
997 public void inputSequence_actionPerformed(ActionEvent e)
999 new SequenceFetcher(this);
1002 JPanel progressPanel;
1004 public void startLoading(final String fileName)
1006 if (fileLoadingCount == 0)
1008 addProgressPanel("Loading File: " + fileName + " ");
1014 private JProgressBar addProgressPanel(String string)
1016 if (progressPanel == null)
1018 progressPanel = new JPanel(new BorderLayout());
1019 totalProgressCount = 0;
1021 JProgressBar progressBar = new JProgressBar();
1022 progressBar.setIndeterminate(true);
1024 progressPanel.add(new JLabel(string), BorderLayout.WEST);
1026 progressPanel.add(progressBar, BorderLayout.CENTER);
1028 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1029 totalProgressCount++;
1034 int totalProgressCount = 0;
1036 private void removeProgressPanel(JProgressBar progbar)
1038 if (progressPanel != null)
1040 progressPanel.remove(progbar);
1041 if (--totalProgressCount < 1)
1043 this.getContentPane().remove(progressPanel);
1044 progressPanel = null;
1050 public void stopLoading()
1053 if (fileLoadingCount < 1)
1055 if (progressPanel != null)
1057 this.getContentPane().remove(progressPanel);
1058 progressPanel = null;
1060 fileLoadingCount = 0;
1065 public static int getViewCount(String viewId)
1067 AlignViewport[] aps = getViewports(viewId);
1068 return (aps == null) ? 0 : aps.length;
1074 * @return all AlignmentPanels concerning the viewId sequence set
1076 public static AlignmentPanel[] getAlignmentPanels(String viewId)
1079 if (Desktop.desktop == null)
1081 // no frames created and in headless mode
1082 // TODO: verify that frames are recoverable when in headless mode
1085 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1086 ArrayList aps = new ArrayList();
1087 for (int t = 0; t < frames.length; t++)
1089 if (frames[t] instanceof AlignFrame)
1091 AlignFrame af = (AlignFrame) frames[t];
1092 for (int a = 0; a < af.alignPanels.size(); a++)
1095 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1096 .getSequenceSetId()))
1098 aps.add(af.alignPanels.elementAt(a));
1103 if (aps.size() == 0)
1107 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1108 for (int t = 0; t < vap.length; t++)
1110 vap[t] = (AlignmentPanel) aps.get(t);
1116 * get all the viewports on an alignment.
1118 * @param sequenceSetId
1119 * unique alignment id
1120 * @return all viewports on the alignment bound to sequenceSetId
1122 public static AlignViewport[] getViewports(String sequenceSetId)
1124 Vector viewp = new Vector();
1125 if (desktop != null)
1127 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1129 for (int t = 0; t < frames.length; t++)
1131 if (frames[t] instanceof AlignFrame)
1133 AlignFrame afr = ((AlignFrame) frames[t]);
1134 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1136 if (afr.alignPanels != null)
1138 for (int a = 0; a < afr.alignPanels.size(); a++)
1140 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1141 .elementAt(a)).av.getSequenceSetId()))
1143 viewp.addElement(((AlignmentPanel) afr.alignPanels
1150 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1155 if (viewp.size() > 0)
1157 AlignViewport[] vp = new AlignViewport[viewp.size()];
1165 public void explodeViews(AlignFrame af)
1167 int size = af.alignPanels.size();
1173 for (int i = 0; i < size; i++)
1175 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1176 AlignFrame newaf = new AlignFrame(ap);
1177 if (ap.av.explodedPosition != null
1178 && !ap.av.explodedPosition.equals(af.getBounds()))
1180 newaf.setBounds(ap.av.explodedPosition);
1183 ap.av.gatherViewsHere = false;
1185 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1186 AlignFrame.DEFAULT_HEIGHT);
1189 af.alignPanels.clear();
1190 af.closeMenuItem_actionPerformed(true);
1194 public void gatherViews(AlignFrame source)
1196 source.viewport.gatherViewsHere = true;
1197 source.viewport.explodedPosition = source.getBounds();
1198 JInternalFrame[] frames = desktop.getAllFrames();
1199 String viewId = source.viewport.sequenceSetID;
1201 for (int t = 0; t < frames.length; t++)
1203 if (frames[t] instanceof AlignFrame && frames[t] != source)
1205 AlignFrame af = (AlignFrame) frames[t];
1206 boolean gatherThis = false;
1207 for (int a = 0; a < af.alignPanels.size(); a++)
1209 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1210 if (viewId.equals(ap.av.getSequenceSetId()))
1213 ap.av.gatherViewsHere = false;
1214 ap.av.explodedPosition = af.getBounds();
1215 source.addAlignmentPanel(ap, false);
1221 af.alignPanels.clear();
1222 af.closeMenuItem_actionPerformed(true);
1229 jalview.gui.VamsasApplication v_client = null;
1231 public void vamsasImport_actionPerformed(ActionEvent e)
1233 if (v_client == null)
1235 // Load and try to start a session.
1236 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1237 .getProperty("LAST_DIRECTORY"));
1239 chooser.setFileView(new JalviewFileView());
1240 chooser.setDialogTitle("Open a saved VAMSAS session");
1242 .setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1244 int value = chooser.showOpenDialog(this);
1246 if (value == JalviewFileChooser.APPROVE_OPTION)
1248 String fle = chooser.getSelectedFile().toString();
1249 if (!vamsasImport(chooser.getSelectedFile()))
1251 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1252 "Couldn't import '" + fle + "' as a new vamsas session.",
1253 "Vamsas Document Import Failed",
1254 JOptionPane.ERROR_MESSAGE);
1260 jalview.bin.Cache.log
1261 .error("Implementation error - load session from a running session is not supported.");
1266 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1269 * @return true if import was a success and a session was started.
1271 public boolean vamsasImport(URL url)
1273 // TODO: create progress bar
1274 if (v_client != null)
1277 jalview.bin.Cache.log
1278 .error("Implementation error - load session from a running session is not supported.");
1284 // copy the URL content to a temporary local file
1285 // TODO: be a bit cleverer here with nio (?!)
1286 File file = File.createTempFile("vdocfromurl", ".vdj");
1287 FileOutputStream fos = new FileOutputStream(file);
1288 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1289 byte[] buffer = new byte[2048];
1291 while ((ln = bis.read(buffer)) > -1)
1293 fos.write(buffer, 0, ln);
1297 v_client = new jalview.gui.VamsasApplication(this, file, url
1299 } catch (Exception ex)
1301 jalview.bin.Cache.log.error(
1302 "Failed to create new vamsas session from contents of URL "
1306 setupVamsasConnectedGui();
1307 v_client.initial_update(); // TODO: thread ?
1308 return v_client.inSession();
1312 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1315 * @return true if import was a success and a session was started.
1317 public boolean vamsasImport(File file)
1319 if (v_client != null)
1322 jalview.bin.Cache.log
1323 .error("Implementation error - load session from a running session is not supported.");
1327 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1331 v_client = new jalview.gui.VamsasApplication(this, file, null);
1332 } catch (Exception ex)
1334 setProgressBar("Importing VAMSAS session from " + file.getName(),
1336 jalview.bin.Cache.log.error(
1337 "New vamsas session from existing session file failed:", ex);
1340 setupVamsasConnectedGui();
1341 v_client.initial_update(); // TODO: thread ?
1342 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1344 return v_client.inSession();
1347 public boolean joinVamsasSession(String mysesid)
1349 if (v_client != null)
1352 "Trying to join a vamsas session when another is already connected.");
1354 if (mysesid == null)
1356 throw new Error("Invalid vamsas session id.");
1358 v_client = new VamsasApplication(this, mysesid);
1359 setupVamsasConnectedGui();
1360 v_client.initial_update();
1361 return (v_client.inSession());
1364 public void vamsasStart_actionPerformed(ActionEvent e)
1366 if (v_client == null)
1369 // we just start a default session for moment.
1371 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1372 * getProperty("LAST_DIRECTORY"));
1374 * chooser.setFileView(new JalviewFileView());
1375 * chooser.setDialogTitle("Load Vamsas file");
1376 * chooser.setToolTipText("Import");
1378 * int value = chooser.showOpenDialog(this);
1380 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1381 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1383 v_client = new VamsasApplication(this);
1384 setupVamsasConnectedGui();
1385 v_client.initial_update(); // TODO: thread ?
1389 // store current data in session.
1390 v_client.push_update(); // TODO: thread
1394 protected void setupVamsasConnectedGui()
1396 vamsasStart.setText("Session Update");
1397 vamsasSave.setVisible(true);
1398 vamsasStop.setVisible(true);
1399 vamsasImport.setVisible(false); // Document import to existing session is
1400 // not possible for vamsas-client-1.0.
1403 protected void setupVamsasDisconnectedGui()
1405 vamsasSave.setVisible(false);
1406 vamsasStop.setVisible(false);
1407 vamsasImport.setVisible(true);
1408 vamsasStart.setText("New Vamsas Session");
1411 public void vamsasStop_actionPerformed(ActionEvent e)
1413 if (v_client != null)
1415 v_client.end_session();
1417 setupVamsasDisconnectedGui();
1421 protected void buildVamsasStMenu()
1423 if (v_client == null)
1425 String[] sess = null;
1428 sess = VamsasApplication.getSessionList();
1429 } catch (Exception e)
1431 jalview.bin.Cache.log.warn(
1432 "Problem getting current sessions list.", e);
1437 jalview.bin.Cache.log.debug("Got current sessions list: "
1438 + sess.length + " entries.");
1439 VamsasStMenu.removeAll();
1440 for (int i = 0; i < sess.length; i++)
1442 JMenuItem sessit = new JMenuItem();
1443 sessit.setText(sess[i]);
1444 sessit.setToolTipText("Connect to session " + sess[i]);
1445 final Desktop dsktp = this;
1446 final String mysesid = sess[i];
1447 sessit.addActionListener(new ActionListener()
1450 public void actionPerformed(ActionEvent e)
1452 if (dsktp.v_client == null)
1454 Thread rthr = new Thread(new Runnable()
1459 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1460 dsktp.setupVamsasConnectedGui();
1461 dsktp.v_client.initial_update();
1469 VamsasStMenu.add(sessit);
1471 // don't show an empty menu.
1472 VamsasStMenu.setVisible(sess.length > 0);
1477 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1478 VamsasStMenu.removeAll();
1479 VamsasStMenu.setVisible(false);
1484 // Not interested in the content. Just hide ourselves.
1485 VamsasStMenu.setVisible(false);
1489 public void vamsasSave_actionPerformed(ActionEvent e)
1491 if (v_client != null)
1493 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1494 .getProperty("LAST_DIRECTORY"), new String[]
1495 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1497 { "Vamsas Document" }, "Vamsas Document");
1499 chooser.setFileView(new JalviewFileView());
1500 chooser.setDialogTitle("Save Vamsas Document Archive");
1502 int value = chooser.showSaveDialog(this);
1504 if (value == JalviewFileChooser.APPROVE_OPTION)
1506 java.io.File choice = chooser.getSelectedFile();
1507 JProgressBar progpanel = addProgressPanel("Saving VAMSAS Document to "
1508 + choice.getName());
1509 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1510 String warnmsg = null;
1511 String warnttl = null;
1514 v_client.vclient.storeDocument(choice);
1517 warnttl = "Serious Problem saving Vamsas Document";
1518 warnmsg = ex.toString();
1519 jalview.bin.Cache.log.error("Error Whilst saving document to "
1522 } catch (Exception ex)
1524 warnttl = "Problem saving Vamsas Document.";
1525 warnmsg = ex.toString();
1526 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1530 removeProgressPanel(progpanel);
1531 if (warnmsg != null)
1533 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1535 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1541 JProgressBar vamUpdate = null;
1544 * hide vamsas user gui bits when a vamsas document event is being handled.
1547 * true to hide gui, false to reveal gui
1549 public void setVamsasUpdate(boolean b)
1551 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
1552 + (b ? "in progress" : "finished"));
1554 if (vamUpdate != null)
1556 this.removeProgressPanel(vamUpdate);
1560 vamUpdate = this.addProgressPanel("Updating vamsas session");
1562 vamsasStart.setVisible(!b);
1563 vamsasStop.setVisible(!b);
1564 vamsasSave.setVisible(!b);
1567 public JInternalFrame[] getAllFrames()
1569 return desktop.getAllFrames();
1573 * Checks the given url to see if it gives a response indicating that the user
1574 * should be informed of a new questionnaire.
1578 public void checkForQuestionnaire(String url)
1580 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
1581 // javax.swing.SwingUtilities.invokeLater(jvq);
1582 new Thread(jvq).start();
1586 * Proxy class for JDesktopPane which optionally displays the current memory
1587 * usage and highlights the desktop area with a red bar if free memory runs
1592 public class MyDesktopPane extends JDesktopPane implements Runnable
1595 boolean showMemoryUsage = false;
1599 java.text.NumberFormat df;
1601 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
1604 public MyDesktopPane(boolean showMemoryUsage)
1606 showMemoryUsage(showMemoryUsage);
1609 public void showMemoryUsage(boolean showMemoryUsage)
1611 this.showMemoryUsage = showMemoryUsage;
1612 if (showMemoryUsage)
1614 Thread worker = new Thread(this);
1619 public boolean isShowMemoryUsage()
1621 return showMemoryUsage;
1626 df = java.text.NumberFormat.getNumberInstance();
1627 df.setMaximumFractionDigits(2);
1628 runtime = Runtime.getRuntime();
1630 while (showMemoryUsage)
1634 maxMemory = runtime.maxMemory() / 1048576f;
1635 allocatedMemory = runtime.totalMemory() / 1048576f;
1636 freeMemory = runtime.freeMemory() / 1048576f;
1637 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
1639 percentUsage = (totalFreeMemory / maxMemory) * 100;
1641 // if (percentUsage < 20)
1643 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
1645 // instance.set.setBorder(border1);
1648 // sleep after showing usage
1650 } catch (Exception ex)
1652 ex.printStackTrace();
1657 public void paintComponent(Graphics g)
1659 if (showMemoryUsage && g != null)
1661 if (percentUsage < 20)
1662 g.setColor(Color.red);
1663 FontMetrics fm = g.getFontMetrics();
1665 { g.drawString("Total Free Memory: " + df.format(totalFreeMemory)
1666 + "MB; Max Memory: " + df.format(maxMemory) + "MB; "
1667 + df.format(percentUsage) + "%", 10, getHeight()
1675 protected JMenuItem groovyShell;
1677 public void doGroovyCheck()
1679 if (jalview.bin.Cache.groovyJarsPresent())
1681 groovyShell = new JMenuItem();
1682 groovyShell.setText("Groovy Console...");
1683 groovyShell.addActionListener(new ActionListener()
1685 public void actionPerformed(ActionEvent e)
1687 groovyShell_actionPerformed(e);
1690 toolsMenu.add(groovyShell);
1691 groovyShell.setVisible(true);
1696 * Accessor method to quickly get all the AlignmentFrames loaded.
1698 public static AlignFrame[] getAlignframes()
1700 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1706 Vector avp = new Vector();
1710 for (int i = frames.length - 1; i > -1; i--)
1712 if (frames[i] instanceof AlignFrame)
1714 AlignFrame af = (AlignFrame) frames[i];
1718 } catch (Exception ex)
1720 ex.printStackTrace();
1722 if (avp.size() == 0)
1726 AlignFrame afs[] = new AlignFrame[avp.size()];
1727 for (int i = 0, j = avp.size(); i < j; i++)
1729 afs[i] = (AlignFrame) avp.elementAt(i);
1736 * Add Groovy Support to Jalview
1738 public void groovyShell_actionPerformed(ActionEvent e)
1740 // use reflection to avoid creating compilation dependency.
1741 if (!jalview.bin.Cache.groovyJarsPresent())
1744 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
1748 Class gcClass = Desktop.class.getClassLoader().loadClass(
1749 "groovy.ui.Console");
1750 Constructor gccons = gcClass.getConstructor(null);
1751 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
1753 { String.class, Object.class });
1754 java.lang.reflect.Method run = gcClass.getMethod("run", null);
1755 Object gc = gccons.newInstance(null);
1756 setvar.invoke(gc, new Object[]
1757 { "Jalview", this });
1758 run.invoke(gc, null);
1759 } catch (Exception ex)
1761 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
1763 .showInternalMessageDialog(
1766 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
1767 "Jalview Groovy Support Failed",
1768 JOptionPane.ERROR_MESSAGE);
1773 * Progress bars managed by the IProgressIndicator method.
1775 private Hashtable progressBars, progressBarHandlers;
1780 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
1782 public void setProgressBar(String message, long id)
1784 if (progressBars == null)
1786 progressBars = new Hashtable();
1787 progressBarHandlers = new Hashtable();
1790 if (progressBars.get(new Long(id)) != null)
1792 JProgressBar progressPanel = (JProgressBar) progressBars
1793 .remove(new Long(id));
1794 if (progressBarHandlers.contains(new Long(id)))
1796 progressBarHandlers.remove(new Long(id));
1798 removeProgressPanel(progressPanel);
1802 progressBars.put(new Long(id), addProgressPanel(message));
1809 * @see jalview.gui.IProgressIndicator#registerHandler(long,
1810 * jalview.gui.IProgressIndicatorHandler)
1812 public void registerHandler(final long id,
1813 final IProgressIndicatorHandler handler)
1815 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
1818 "call setProgressBar before registering the progress bar's handler.");
1820 progressBarHandlers.put(new Long(id), handler);
1821 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
1822 if (handler.canCancel())
1824 JButton cancel = new JButton("Cancel");
1825 final IProgressIndicator us = this;
1826 cancel.addActionListener(new ActionListener()
1829 public void actionPerformed(ActionEvent e)
1831 handler.cancelActivity(id);
1832 us.setProgressBar("Cancelled "
1833 + ((JLabel) progressPanel.getComponent(0)).getText(), id);
1836 progressPanel.add(cancel, BorderLayout.EAST);
1841 * This will return the first AlignFrame viewing AlignViewport av. It will
1842 * break if there are more than one AlignFrames viewing a particular av. This
1845 * @return alignFrame for av
1847 public static AlignFrame getAlignFrameFor(AlignViewport av)
1849 if (desktop != null)
1851 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
1852 for (int panel = 0; aps != null && panel < aps.length; panel++)
1854 if (aps[panel] != null && aps[panel].av == av)
1856 return aps[panel].alignFrame;
1863 public VamsasApplication getVamsasApplication()