2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
21 import jalview.io.FileLoader;
22 import jalview.io.FormatAdapter;
23 import jalview.io.IdentifyFile;
24 import jalview.io.JalviewFileChooser;
25 import jalview.io.JalviewFileView;
26 import jalview.ws.params.ParamManager;
28 import java.awt.BorderLayout;
29 import java.awt.Color;
30 import java.awt.Dimension;
31 import java.awt.FontMetrics;
32 import java.awt.Graphics;
33 import java.awt.GridLayout;
34 import java.awt.Point;
35 import java.awt.Rectangle;
36 import java.awt.Toolkit;
37 import java.awt.datatransfer.Clipboard;
38 import java.awt.datatransfer.ClipboardOwner;
39 import java.awt.datatransfer.DataFlavor;
40 import java.awt.datatransfer.Transferable;
41 import java.awt.dnd.DnDConstants;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetEvent;
45 import java.awt.dnd.DropTargetListener;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.awt.event.MouseAdapter;
51 import java.awt.event.MouseEvent;
52 import java.awt.event.MouseListener;
53 import java.awt.event.WindowAdapter;
54 import java.awt.event.WindowEvent;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.beans.PropertyVetoException;
58 import java.io.BufferedInputStream;
60 import java.io.FileOutputStream;
61 import java.lang.reflect.Constructor;
63 import java.util.ArrayList;
64 import java.util.Hashtable;
65 import java.util.StringTokenizer;
66 import java.util.Vector;
67 import java.util.concurrent.ExecutorService;
68 import java.util.concurrent.Executors;
70 import javax.swing.DefaultDesktopManager;
71 import javax.swing.DesktopManager;
72 import javax.swing.JButton;
73 import javax.swing.JComboBox;
74 import javax.swing.JComponent;
75 import javax.swing.JDesktopPane;
76 import javax.swing.JFrame;
77 import javax.swing.JInternalFrame;
78 import javax.swing.JLabel;
79 import javax.swing.JMenuItem;
80 import javax.swing.JOptionPane;
81 import javax.swing.JPanel;
82 import javax.swing.JPopupMenu;
83 import javax.swing.JProgressBar;
84 import javax.swing.SwingUtilities;
85 import javax.swing.event.HyperlinkEvent;
86 import javax.swing.event.MenuEvent;
87 import javax.swing.event.MenuListener;
88 import javax.swing.event.HyperlinkEvent.EventType;
95 * @version $Revision: 1.155 $
97 public class Desktop extends jalview.jbgui.GDesktop implements
98 DropTargetListener, ClipboardOwner, IProgressIndicator, jalview.api.StructureSelectionManagerProvider
101 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
104 * news reader - null if it was never started.
106 private BlogReader jvnews=null;
110 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
112 public void addJalviewPropertyChangeListener(
113 PropertyChangeListener listener)
115 changeSupport.addJalviewPropertyChangeListener(listener);
119 * @param propertyName
121 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
122 * java.beans.PropertyChangeListener)
124 public void addJalviewPropertyChangeListener(String propertyName,
125 PropertyChangeListener listener)
127 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
131 * @param propertyName
133 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
134 * java.beans.PropertyChangeListener)
136 public void removeJalviewPropertyChangeListener(String propertyName,
137 PropertyChangeListener listener)
139 changeSupport.removeJalviewPropertyChangeListener(propertyName,
143 /** Singleton Desktop instance */
144 public static Desktop instance;
146 public static MyDesktopPane desktop;
148 static int openFrameCount = 0;
150 static final int xOffset = 30;
152 static final int yOffset = 30;
154 public static jalview.ws.jws1.Discoverer discoverer;
156 public static Object[] jalviewClipboard;
158 public static boolean internalCopy = false;
160 static int fileLoadingCount = 0;
162 class MyDesktopManager implements DesktopManager
165 private DesktopManager delegate;
167 public MyDesktopManager(DesktopManager delegate)
169 this.delegate = delegate;
172 public void activateFrame(JInternalFrame f)
176 delegate.activateFrame(f);
177 } catch (NullPointerException npe)
179 Point p = getMousePosition();
180 instance.showPasteMenu(p.x, p.y);
184 public void beginDraggingFrame(JComponent f)
186 delegate.beginDraggingFrame(f);
189 public void beginResizingFrame(JComponent f, int direction)
191 delegate.beginResizingFrame(f, direction);
194 public void closeFrame(JInternalFrame f)
196 delegate.closeFrame(f);
199 public void deactivateFrame(JInternalFrame f)
201 delegate.deactivateFrame(f);
204 public void deiconifyFrame(JInternalFrame f)
206 delegate.deiconifyFrame(f);
209 public void dragFrame(JComponent f, int newX, int newY)
215 delegate.dragFrame(f, newX, newY);
218 public void endDraggingFrame(JComponent f)
220 delegate.endDraggingFrame(f);
223 public void endResizingFrame(JComponent f)
225 delegate.endResizingFrame(f);
228 public void iconifyFrame(JInternalFrame f)
230 delegate.iconifyFrame(f);
233 public void maximizeFrame(JInternalFrame f)
235 delegate.maximizeFrame(f);
238 public void minimizeFrame(JInternalFrame f)
240 delegate.minimizeFrame(f);
243 public void openFrame(JInternalFrame f)
245 delegate.openFrame(f);
248 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
251 Rectangle b=desktop.getBounds();
256 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
259 public void setBoundsForFrame(JComponent f, int newX, int newY,
260 int newWidth, int newHeight)
262 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
265 // All other methods, simply delegate
270 * Creates a new Desktop object.
275 * A note to implementors. It is ESSENTIAL that any activities that might
276 * block are spawned off as threads rather than waited for during this
280 doVamsasClientCheck();
283 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
284 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
285 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
287 boolean showjconsole = jalview.bin.Cache.getDefault(
288 "SHOW_JAVA_CONSOLE", false);
289 desktop = new MyDesktopPane(selmemusage);
290 showMemusage.setSelected(selmemusage);
291 desktop.setBackground(Color.white);
292 getContentPane().setLayout(new BorderLayout());
293 // alternate config - have scrollbars - see notes in JAL-153
294 //JScrollPane sp = new JScrollPane();
295 //sp.getViewport().setView(desktop);
296 //getContentPane().add(sp, BorderLayout.CENTER);
297 getContentPane().add(desktop, BorderLayout.CENTER);
298 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
301 // This line prevents Windows Look&Feel resizing all new windows to maximum
302 // if previous window was maximised
303 desktop.setDesktopManager(new MyDesktopManager(
304 new DefaultDesktopManager()));
306 Rectangle dims = getLastKnownDimensions("");
313 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
314 setBounds((int) (screenSize.width - 900) / 2,
315 (int) (screenSize.height - 650) / 2, 900, 650);
317 jconsole = new Console(this, showjconsole);
318 // add essential build information
319 jconsole.setHeader("Jalview Desktop "
320 + jalview.bin.Cache.getProperty("VERSION") + "\n"
322 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
323 + "Java version: " + System.getProperty("java.version") + "\n"
324 + System.getProperty("os.arch") + " "
325 + System.getProperty("os.name") + " "
326 + System.getProperty("os.version"));
328 showConsole(showjconsole);
330 showNews.setVisible(false);
332 this.addWindowListener(new WindowAdapter()
334 public void windowClosing(WindowEvent evt)
341 this.addMouseListener(ma=new MouseAdapter()
343 public void mousePressed(MouseEvent evt)
345 if (SwingUtilities.isRightMouseButton(evt))
347 showPasteMenu(evt.getX(), evt.getY());
351 desktop.addMouseListener(ma);
353 this.addFocusListener(new FocusListener()
357 public void focusLost(FocusEvent e)
359 // TODO Auto-generated method stub
364 public void focusGained(FocusEvent e)
366 Cache.log.debug("Relaying windows after focus gain");
367 // make sure that we sort windows properly after we gain focus
368 instance.relayerWindows();
371 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
372 // Spawn a thread that shows the splashscreen
373 SwingUtilities.invokeLater(new Runnable()
382 // Thread off a new instance of the file chooser - this reduces the time it
383 // takes to open it later on.
384 new Thread(new Runnable()
388 Cache.log.debug("Filechooser init thread started.");
389 JalviewFileChooser chooser = new JalviewFileChooser(
390 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
391 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
392 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
393 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
394 Cache.log.debug("Filechooser init thread finished.");
397 // Add the service change listener
398 changeSupport.addJalviewPropertyChangeListener("services",
399 new PropertyChangeListener()
403 public void propertyChange(PropertyChangeEvent evt)
405 Cache.log.debug("Firing service changed event for "
406 + evt.getNewValue());
407 JalviewServicesChanged(evt);
413 public void checkForNews()
415 final Desktop me = this;
416 // Thread off the news reader, in case there are connection problems.
417 addDialogThread(new Runnable() {
421 Cache.log.debug("Starting news thread.");
423 jvnews = new BlogReader(me);
424 showNews.setVisible(true);
425 Cache.log.debug("Completed news thread.");
429 protected void showNews_actionPerformed(ActionEvent e)
431 showNews(showNews.isSelected());
433 void showNews(boolean visible)
436 Cache.log.debug((visible?"Showing":"Hiding")+" news.");
437 showNews.setSelected(visible);
438 if (visible && !jvnews.isVisible())
440 new Thread(new Runnable() {
444 long instance=System.currentTimeMillis();
445 Desktop.instance.setProgressBar("Refreshing news", instance);
446 jvnews.refreshNews();
447 Desktop.instance.setProgressBar(null, instance);
456 * recover the last known dimensions for a jalview window
459 * - empty string is desktop, all other windows have unique prefix
460 * @return null or last known dimensions scaled to current geometry (if last
461 * window geom was known)
463 Rectangle getLastKnownDimensions(String windowName)
465 // TODO: lock aspect ratio for scaling desktop Bug #0058199
466 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
467 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
468 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
469 String width = jalview.bin.Cache.getProperty(windowName
471 String height = jalview.bin.Cache.getProperty(windowName
473 if ((x != null) && (y != null) && (width != null) && (height != null))
475 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
476 .parseInt(width), ih = Integer.parseInt(height);
477 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
479 // attempt #1 - try to cope with change in screen geometry - this
480 // version doesn't preserve original jv aspect ratio.
481 // take ratio of current screen size vs original screen size.
482 double sw = ((1f * screenSize.width) / (1f * Integer
483 .parseInt(jalview.bin.Cache
484 .getProperty("SCREENGEOMETRY_WIDTH"))));
485 double sh = ((1f * screenSize.height) / (1f * Integer
486 .parseInt(jalview.bin.Cache
487 .getProperty("SCREENGEOMETRY_HEIGHT"))));
488 // rescale the bounds depending upon the current screen geometry.
489 ix = (int) (ix * sw);
490 iw = (int) (iw * sw);
491 iy = (int) (iy * sh);
492 ih = (int) (ih * sh);
493 while (ix >= screenSize.width)
495 jalview.bin.Cache.log
496 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
497 ix -= screenSize.width;
499 while (iy >= screenSize.height)
501 jalview.bin.Cache.log
502 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
503 iy -= screenSize.height;
505 jalview.bin.Cache.log.debug("Got last known dimensions for "
506 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
509 // return dimensions for new instance
510 return new Rectangle(ix, iy, iw, ih);
515 private void doVamsasClientCheck()
517 if (jalview.bin.Cache.vamsasJarsPresent())
519 setupVamsasDisconnectedGui();
520 VamsasMenu.setVisible(true);
521 final Desktop us = this;
522 VamsasMenu.addMenuListener(new MenuListener()
524 // this listener remembers when the menu was first selected, and
525 // doesn't rebuild the session list until it has been cleared and
527 boolean refresh = true;
529 public void menuCanceled(MenuEvent e)
534 public void menuDeselected(MenuEvent e)
539 public void menuSelected(MenuEvent e)
543 us.buildVamsasStMenu();
548 vamsasStart.setVisible(true);
552 void showPasteMenu(int x, int y)
554 JPopupMenu popup = new JPopupMenu();
555 JMenuItem item = new JMenuItem("Paste To New Window");
556 item.addActionListener(new ActionListener()
558 public void actionPerformed(ActionEvent evt)
565 popup.show(this, x, y);
572 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
573 Transferable contents = c.getContents(this);
575 if (contents != null)
577 String file = (String) contents
578 .getTransferData(DataFlavor.stringFlavor);
580 String format = new IdentifyFile().Identify(file,
581 FormatAdapter.PASTE);
583 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
586 } catch (Exception ex)
589 .println("Unable to paste alignment from system clipboard:\n"
595 * Adds and opens the given frame to the desktop
606 public static synchronized void addInternalFrame(
607 final JInternalFrame frame, String title, int w, int h)
609 addInternalFrame(frame, title, w, h, true);
626 public static synchronized void addInternalFrame(
627 final JInternalFrame frame, String title, int w, int h,
631 // TODO: allow callers to determine X and Y position of frame (eg. via
633 // TODO: consider fixing method to update entries in the window submenu with
634 // the current window title
636 frame.setTitle(title);
637 if (frame.getWidth() < 1 || frame.getHeight() < 1)
641 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
642 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
643 // IF JALVIEW IS RUNNING HEADLESS
644 // ///////////////////////////////////////////////
645 if (System.getProperty("java.awt.headless") != null
646 && System.getProperty("java.awt.headless").equals("true"))
653 frame.setVisible(true);
654 frame.setClosable(true);
655 frame.setResizable(resizable);
656 frame.setMaximizable(resizable);
657 frame.setIconifiable(resizable);
658 frame.setFrameIcon(null);
660 if (frame.getX() < 1 && frame.getY() < 1)
662 frame.setLocation(xOffset * openFrameCount, yOffset
663 * ((openFrameCount - 1) % 10) + yOffset);
666 final JMenuItem menuItem = new JMenuItem(title);
667 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
669 public void internalFrameActivated(
670 javax.swing.event.InternalFrameEvent evt)
672 JInternalFrame itf = desktop.getSelectedFrame();
680 public void internalFrameClosed(
681 javax.swing.event.InternalFrameEvent evt)
683 PaintRefresher.RemoveComponent(frame);
685 windowMenu.remove(menuItem);
686 JInternalFrame itf = desktop.getSelectedFrame();
695 menuItem.addActionListener(new ActionListener()
697 public void actionPerformed(ActionEvent e)
701 frame.setSelected(true);
702 frame.setIcon(false);
703 } catch (java.beans.PropertyVetoException ex)
709 menuItem.addMouseListener(new MouseListener()
713 public void mouseReleased(MouseEvent e)
718 public void mousePressed(MouseEvent e)
723 public void mouseExited(MouseEvent e)
727 frame.setSelected(false);
728 } catch (PropertyVetoException e1)
734 public void mouseEntered(MouseEvent e)
738 frame.setSelected(true);
739 } catch (PropertyVetoException e1)
745 public void mouseClicked(MouseEvent e)
751 windowMenu.add(menuItem);
757 frame.setSelected(true);
758 frame.requestFocus();
759 } catch (java.beans.PropertyVetoException ve)
762 catch (java.lang.ClassCastException cex)
764 Cache.log.warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",cex);
768 public void lostOwnership(Clipboard clipboard, Transferable contents)
772 Desktop.jalviewClipboard = null;
775 internalCopy = false;
778 public void dragEnter(DropTargetDragEvent evt)
782 public void dragExit(DropTargetEvent evt)
786 public void dragOver(DropTargetDragEvent evt)
790 public void dropActionChanged(DropTargetDragEvent evt)
800 public void drop(DropTargetDropEvent evt)
802 Transferable t = evt.getTransferable();
803 java.util.List files = null;
804 java.util.List protocols = null;
808 DataFlavor uriListFlavor = new DataFlavor(
809 "text/uri-list;class=java.lang.String");
810 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
812 // Works on Windows and MacOSX
813 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
814 files = (java.util.List) t
815 .getTransferData(DataFlavor.javaFileListFlavor);
817 else if (t.isDataFlavorSupported(uriListFlavor))
819 // This is used by Unix drag system
820 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
821 String data = (String) t.getTransferData(uriListFlavor);
822 files = new java.util.ArrayList(1);
823 protocols = new java.util.ArrayList(1);
824 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
825 data, "\r\n"); st.hasMoreTokens();)
827 String s = st.nextToken();
828 if (s.startsWith("#"))
830 // the line is a comment (as per the RFC 2483)
833 java.net.URI uri = new java.net.URI(s);
834 if (uri.getScheme().toLowerCase().startsWith("http"))
836 protocols.add(FormatAdapter.URL);
837 files.add(uri.toString());
841 // otherwise preserve old behaviour: catch all for file objects
842 java.io.File file = new java.io.File(uri);
843 protocols.add(FormatAdapter.FILE);
844 files.add(file.toString());
848 } catch (Exception e)
856 for (int i = 0; i < files.size(); i++)
858 String file = files.get(i).toString();
859 String protocol = (protocols == null) ? FormatAdapter.FILE
860 : (String) protocols.get(i);
861 String format = null;
863 if (file.endsWith(".jar"))
870 format = new IdentifyFile().Identify(file, protocol);
873 new FileLoader().LoadFile(file, protocol, format);
876 } catch (Exception ex)
888 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
890 JalviewFileChooser chooser = new JalviewFileChooser(
891 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
892 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
893 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
894 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
896 chooser.setFileView(new JalviewFileView());
897 chooser.setDialogTitle("Open local file");
898 chooser.setToolTipText("Open");
900 int value = chooser.showOpenDialog(this);
902 if (value == JalviewFileChooser.APPROVE_OPTION)
904 String choice = chooser.getSelectedFile().getPath();
905 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
906 .getSelectedFile().getParent());
908 String format = null;
909 if (chooser.getSelectedFormat().equals("Jalview"))
915 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
918 if (viewport != null)
920 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
925 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
936 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
938 // This construct allows us to have a wider textfield
940 JLabel label = new JLabel("Enter URL of Input File");
941 final JComboBox history = new JComboBox();
943 JPanel panel = new JPanel(new GridLayout(2, 1));
946 history.setPreferredSize(new Dimension(400, 20));
947 history.setEditable(true);
948 history.addItem("http://www.");
950 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
954 if (historyItems != null)
956 st = new StringTokenizer(historyItems, "\t");
958 while (st.hasMoreTokens())
960 history.addItem(st.nextElement());
964 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
965 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
967 if (reply != JOptionPane.OK_OPTION)
972 String url = history.getSelectedItem().toString();
974 if (url.toLowerCase().endsWith(".jar"))
976 if (viewport != null)
978 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
983 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
988 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
990 if (format.equals("URL NOT FOUND"))
992 JOptionPane.showInternalMessageDialog(Desktop.desktop,
993 "Couldn't locate " + url, "URL not found",
994 JOptionPane.WARNING_MESSAGE);
999 if (viewport != null)
1001 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1005 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1016 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1018 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1019 cap.setForInput(viewport);
1020 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1028 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1030 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1031 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1033 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1034 getBounds().y, getWidth(), getHeight()));
1036 if (jconsole != null)
1038 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1039 jconsole.stopConsole();
1043 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1046 if (dialogExecutor!=null)
1048 dialogExecutor.shutdownNow();
1054 private void storeLastKnownDimensions(String string, Rectangle jc)
1056 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1057 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1058 + " height:" + jc.height);
1060 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1061 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1062 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1063 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1072 public void aboutMenuItem_actionPerformed(ActionEvent e)
1074 // StringBuffer message = getAboutMessage(false);
1075 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1077 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1078 new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
1081 public StringBuffer getAboutMessage(boolean shortv)
1083 StringBuffer message = new StringBuffer();
1084 message.append("<html>");
1087 message.append("<h1><strong>Version: "
1088 + jalview.bin.Cache.getProperty("VERSION")
1089 + "</strong></h1><br>");
1090 message.append("<strong>Last Updated: <em>"
1091 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1092 + "</em></strong>");
1098 message.append("<strong>Version "
1099 + jalview.bin.Cache.getProperty("VERSION")
1100 + "; last updated: "
1101 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1104 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1107 message.append("<br>...Checking latest version...</br>");
1109 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1110 .equals(jalview.bin.Cache.getProperty("VERSION")))
1112 boolean red = false;
1113 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1114 .indexOf("automated build") == -1)
1117 // Displayed when code version and jnlp version do not match and code
1118 // version is not a development build
1119 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1122 message.append("<br>!! Version "
1123 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1125 + " is available for download from "
1126 + jalview.bin.Cache.getDefault("www.jalview.org",
1127 "http://www.jalview.org") + " !!");
1130 message.append("</div>");
1133 message.append("<br>Authors: "
1137 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1138 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1139 + "<br>For help, see the FAQ at <a href=\"http://www.jalview.org\">www.jalview.org</a> and/or join the jalview-discuss@jalview.org mailing list"
1140 + "<br>If you use Jalview, please cite:"
1141 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1142 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1143 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1154 public void documentationMenuItem_actionPerformed(ActionEvent e)
1158 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1159 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1160 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1162 javax.help.HelpBroker hb = hs.createHelpBroker();
1163 hb.setCurrentID("home");
1164 hb.setDisplayed(true);
1165 } catch (Exception ex)
1170 public void closeAll_actionPerformed(ActionEvent e)
1172 JInternalFrame[] frames = desktop.getAllFrames();
1173 for (int i = 0; i < frames.length; i++)
1177 frames[i].setClosed(true);
1178 } catch (java.beans.PropertyVetoException ex)
1182 System.out.println("ALL CLOSED");
1183 if (v_client != null)
1185 // TODO clear binding to vamsas document objects on close_all
1190 public void raiseRelated_actionPerformed(ActionEvent e)
1192 reorderAssociatedWindows(false, false);
1195 public void minimizeAssociated_actionPerformed(ActionEvent e)
1197 reorderAssociatedWindows(true, false);
1200 void closeAssociatedWindows()
1202 reorderAssociatedWindows(false, true);
1208 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1211 protected void garbageCollect_actionPerformed(ActionEvent e)
1213 // We simply collect the garbage
1214 jalview.bin.Cache.log.debug("Collecting garbage...");
1216 jalview.bin.Cache.log.debug("Finished garbage collection.");
1223 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1226 protected void showMemusage_actionPerformed(ActionEvent e)
1228 desktop.showMemoryUsage(showMemusage.isSelected());
1235 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1238 protected void showConsole_actionPerformed(ActionEvent e)
1240 showConsole(showConsole.isSelected());
1243 Console jconsole = null;
1246 * control whether the java console is visible or not
1250 void showConsole(boolean selected)
1252 showConsole.setSelected(selected);
1253 // TODO: decide if we should update properties file
1254 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1256 jconsole.setVisible(selected);
1259 void reorderAssociatedWindows(boolean minimize, boolean close)
1261 JInternalFrame[] frames = desktop.getAllFrames();
1262 if (frames == null || frames.length < 1)
1267 AlignViewport source = null, target = null;
1268 if (frames[0] instanceof AlignFrame)
1270 source = ((AlignFrame) frames[0]).getCurrentView();
1272 else if (frames[0] instanceof TreePanel)
1274 source = ((TreePanel) frames[0]).getViewPort();
1276 else if (frames[0] instanceof PCAPanel)
1278 source = ((PCAPanel) frames[0]).av;
1280 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1282 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1287 for (int i = 0; i < frames.length; i++)
1290 if (frames[i] == null)
1294 if (frames[i] instanceof AlignFrame)
1296 target = ((AlignFrame) frames[i]).getCurrentView();
1298 else if (frames[i] instanceof TreePanel)
1300 target = ((TreePanel) frames[i]).getViewPort();
1302 else if (frames[i] instanceof PCAPanel)
1304 target = ((PCAPanel) frames[i]).av;
1306 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1308 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1311 if (source == target)
1317 frames[i].setClosed(true);
1321 frames[i].setIcon(minimize);
1324 frames[i].toFront();
1328 } catch (java.beans.PropertyVetoException ex)
1342 protected void preferences_actionPerformed(ActionEvent e)
1353 public void saveState_actionPerformed(ActionEvent e)
1355 JalviewFileChooser chooser = new JalviewFileChooser(
1356 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1357 { "jar" }, new String[]
1358 { "Jalview Project" }, "Jalview Project");
1360 chooser.setFileView(new JalviewFileView());
1361 chooser.setDialogTitle("Save State");
1363 int value = chooser.showSaveDialog(this);
1365 if (value == JalviewFileChooser.APPROVE_OPTION)
1367 final Desktop me = this;
1368 final java.io.File choice = chooser.getSelectedFile();
1369 new Thread(new Runnable()
1374 setProgressBar("Saving jalview project " + choice.getName(),
1376 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1377 // TODO catch and handle errors for savestate
1378 // TODO prevent user from messing with the Desktop whilst we're saving
1381 new Jalview2XML().SaveState(choice);
1382 } catch (OutOfMemoryError oom)
1385 "Whilst saving current state to " + choice.getName(), oom);
1386 } catch (Exception ex)
1389 .error("Problems whilst trying to save to "
1390 + choice.getName(), ex);
1391 JOptionPane.showMessageDialog(me,
1392 "Error whilst saving current state to " + choice.getName(),
1393 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1395 setProgressBar(null, choice.hashCode());
1407 public void loadState_actionPerformed(ActionEvent e)
1409 JalviewFileChooser chooser = new JalviewFileChooser(
1410 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1411 { "jar" }, new String[]
1412 { "Jalview Project" }, "Jalview Project");
1413 chooser.setFileView(new JalviewFileView());
1414 chooser.setDialogTitle("Restore state");
1416 int value = chooser.showOpenDialog(this);
1418 if (value == JalviewFileChooser.APPROVE_OPTION)
1420 final String choice = chooser.getSelectedFile().getAbsolutePath();
1421 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1422 .getSelectedFile().getParent());
1423 new Thread(new Runnable()
1427 setProgressBar("loading jalview project " + choice,
1431 new Jalview2XML().LoadJalviewAlign(choice);
1432 } catch (OutOfMemoryError oom)
1434 new OOMWarning("Whilst loading project from " + choice, oom);
1435 } catch (Exception ex)
1437 Cache.log.error("Problems whilst loading project from "
1439 JOptionPane.showMessageDialog(Desktop.desktop,
1440 "Error whilst loading project from " + choice,
1441 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1443 setProgressBar(null, choice.hashCode());
1449 public void inputSequence_actionPerformed(ActionEvent e)
1451 new SequenceFetcher(this);
1454 JPanel progressPanel;
1455 ArrayList<JPanel> fileLoadingPanels=new ArrayList<JPanel>();
1456 public void startLoading(final String fileName)
1458 if (fileLoadingCount == 0)
1460 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName + " "));
1465 private JPanel addProgressPanel(String string)
1467 if (progressPanel == null)
1469 progressPanel = new JPanel(new GridLayout(1,1));
1470 totalProgressCount = 0;
1471 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1473 JPanel thisprogress=new JPanel(new BorderLayout(10,5));
1474 JProgressBar progressBar = new JProgressBar();
1475 progressBar.setIndeterminate(true);
1477 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1479 thisprogress.add(progressBar, BorderLayout.CENTER);
1480 progressPanel.add(thisprogress);
1481 ((GridLayout)progressPanel.getLayout()).setRows(((GridLayout)progressPanel.getLayout()).getRows()+1);
1482 ++totalProgressCount;
1483 instance.validate();
1484 return thisprogress;
1487 int totalProgressCount = 0;
1489 private void removeProgressPanel(JPanel progbar)
1491 if (progressPanel != null)
1493 progressPanel.remove(progbar);
1494 GridLayout gl = (GridLayout) progressPanel.getLayout();
1495 gl.setRows(gl.getRows()-1);
1496 if (--totalProgressCount < 1)
1498 this.getContentPane().remove(progressPanel);
1499 progressPanel = null;
1505 public void stopLoading()
1508 if (fileLoadingCount < 1)
1510 for (JPanel flp : fileLoadingPanels)
1512 removeProgressPanel(flp);
1514 fileLoadingPanels.clear();
1515 fileLoadingCount = 0;
1520 public static int getViewCount(String alignmentId)
1522 AlignViewport[] aps = getViewports(alignmentId);
1523 return (aps == null) ? 0 : aps.length;
1528 * @param alignmentId
1529 * @return all AlignmentPanels concerning the alignmentId sequence set
1531 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1534 if (Desktop.desktop == null)
1536 // no frames created and in headless mode
1537 // TODO: verify that frames are recoverable when in headless mode
1540 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1541 ArrayList aps = new ArrayList();
1542 for (int t = 0; t < frames.length; t++)
1544 if (frames[t] instanceof AlignFrame)
1546 AlignFrame af = (AlignFrame) frames[t];
1547 for (int a = 0; a < af.alignPanels.size(); a++)
1550 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1551 .getSequenceSetId()))
1553 aps.add(af.alignPanels.elementAt(a));
1558 if (aps.size() == 0)
1562 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1563 for (int t = 0; t < vap.length; t++)
1565 vap[t] = (AlignmentPanel) aps.get(t);
1571 * get all the viewports on an alignment.
1573 * @param sequenceSetId
1574 * unique alignment id
1575 * @return all viewports on the alignment bound to sequenceSetId
1577 public static AlignViewport[] getViewports(String sequenceSetId)
1579 Vector viewp = new Vector();
1580 if (desktop != null)
1582 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1584 for (int t = 0; t < frames.length; t++)
1586 if (frames[t] instanceof AlignFrame)
1588 AlignFrame afr = ((AlignFrame) frames[t]);
1589 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1591 if (afr.alignPanels != null)
1593 for (int a = 0; a < afr.alignPanels.size(); a++)
1595 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1596 .elementAt(a)).av.getSequenceSetId()))
1598 viewp.addElement(((AlignmentPanel) afr.alignPanels
1605 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1610 if (viewp.size() > 0)
1612 AlignViewport[] vp = new AlignViewport[viewp.size()];
1620 public void explodeViews(AlignFrame af)
1622 int size = af.alignPanels.size();
1628 for (int i = 0; i < size; i++)
1630 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1631 AlignFrame newaf = new AlignFrame(ap);
1632 if (ap.av.explodedPosition != null
1633 && !ap.av.explodedPosition.equals(af.getBounds()))
1635 newaf.setBounds(ap.av.explodedPosition);
1638 ap.av.gatherViewsHere = false;
1640 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1641 AlignFrame.DEFAULT_HEIGHT);
1644 af.alignPanels.clear();
1645 af.closeMenuItem_actionPerformed(true);
1649 public void gatherViews(AlignFrame source)
1651 source.viewport.gatherViewsHere = true;
1652 source.viewport.explodedPosition = source.getBounds();
1653 JInternalFrame[] frames = desktop.getAllFrames();
1654 String viewId = source.viewport.getSequenceSetId();
1656 for (int t = 0; t < frames.length; t++)
1658 if (frames[t] instanceof AlignFrame && frames[t] != source)
1660 AlignFrame af = (AlignFrame) frames[t];
1661 boolean gatherThis = false;
1662 for (int a = 0; a < af.alignPanels.size(); a++)
1664 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1665 if (viewId.equals(ap.av.getSequenceSetId()))
1668 ap.av.gatherViewsHere = false;
1669 ap.av.explodedPosition = af.getBounds();
1670 source.addAlignmentPanel(ap, false);
1676 af.alignPanels.clear();
1677 af.closeMenuItem_actionPerformed(true);
1684 jalview.gui.VamsasApplication v_client = null;
1686 public void vamsasImport_actionPerformed(ActionEvent e)
1688 if (v_client == null)
1690 // Load and try to start a session.
1691 JalviewFileChooser chooser = new JalviewFileChooser(
1692 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1694 chooser.setFileView(new JalviewFileView());
1695 chooser.setDialogTitle("Open a saved VAMSAS session");
1696 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1698 int value = chooser.showOpenDialog(this);
1700 if (value == JalviewFileChooser.APPROVE_OPTION)
1702 String fle = chooser.getSelectedFile().toString();
1703 if (!vamsasImport(chooser.getSelectedFile()))
1705 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1706 "Couldn't import '" + fle + "' as a new vamsas session.",
1707 "Vamsas Document Import Failed",
1708 JOptionPane.ERROR_MESSAGE);
1714 jalview.bin.Cache.log
1715 .error("Implementation error - load session from a running session is not supported.");
1720 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1723 * @return true if import was a success and a session was started.
1725 public boolean vamsasImport(URL url)
1727 // TODO: create progress bar
1728 if (v_client != null)
1731 jalview.bin.Cache.log
1732 .error("Implementation error - load session from a running session is not supported.");
1738 // copy the URL content to a temporary local file
1739 // TODO: be a bit cleverer here with nio (?!)
1740 File file = File.createTempFile("vdocfromurl", ".vdj");
1741 FileOutputStream fos = new FileOutputStream(file);
1742 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1743 byte[] buffer = new byte[2048];
1745 while ((ln = bis.read(buffer)) > -1)
1747 fos.write(buffer, 0, ln);
1751 v_client = new jalview.gui.VamsasApplication(this, file,
1752 url.toExternalForm());
1753 } catch (Exception ex)
1755 jalview.bin.Cache.log.error(
1756 "Failed to create new vamsas session from contents of URL "
1760 setupVamsasConnectedGui();
1761 v_client.initial_update(); // TODO: thread ?
1762 return v_client.inSession();
1766 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1769 * @return true if import was a success and a session was started.
1771 public boolean vamsasImport(File file)
1773 if (v_client != null)
1776 jalview.bin.Cache.log
1777 .error("Implementation error - load session from a running session is not supported.");
1781 setProgressBar("Importing VAMSAS session from " + file.getName(),
1785 v_client = new jalview.gui.VamsasApplication(this, file, null);
1786 } catch (Exception ex)
1788 setProgressBar("Importing VAMSAS session from " + file.getName(),
1790 jalview.bin.Cache.log.error(
1791 "New vamsas session from existing session file failed:", ex);
1794 setupVamsasConnectedGui();
1795 v_client.initial_update(); // TODO: thread ?
1796 setProgressBar("Importing VAMSAS session from " + file.getName(),
1798 return v_client.inSession();
1801 public boolean joinVamsasSession(String mysesid)
1803 if (v_client != null)
1806 "Trying to join a vamsas session when another is already connected.");
1808 if (mysesid == null)
1810 throw new Error("Invalid vamsas session id.");
1812 v_client = new VamsasApplication(this, mysesid);
1813 setupVamsasConnectedGui();
1814 v_client.initial_update();
1815 return (v_client.inSession());
1818 public void vamsasStart_actionPerformed(ActionEvent e)
1820 if (v_client == null)
1823 // we just start a default session for moment.
1825 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1826 * getProperty("LAST_DIRECTORY"));
1828 * chooser.setFileView(new JalviewFileView());
1829 * chooser.setDialogTitle("Load Vamsas file");
1830 * chooser.setToolTipText("Import");
1832 * int value = chooser.showOpenDialog(this);
1834 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1835 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1837 v_client = new VamsasApplication(this);
1838 setupVamsasConnectedGui();
1839 v_client.initial_update(); // TODO: thread ?
1843 // store current data in session.
1844 v_client.push_update(); // TODO: thread
1848 protected void setupVamsasConnectedGui()
1850 vamsasStart.setText("Session Update");
1851 vamsasSave.setVisible(true);
1852 vamsasStop.setVisible(true);
1853 vamsasImport.setVisible(false); // Document import to existing session is
1854 // not possible for vamsas-client-1.0.
1857 protected void setupVamsasDisconnectedGui()
1859 vamsasSave.setVisible(false);
1860 vamsasStop.setVisible(false);
1861 vamsasImport.setVisible(true);
1862 vamsasStart.setText("New Vamsas Session");
1865 public void vamsasStop_actionPerformed(ActionEvent e)
1867 if (v_client != null)
1869 v_client.end_session();
1871 setupVamsasDisconnectedGui();
1875 protected void buildVamsasStMenu()
1877 if (v_client == null)
1879 String[] sess = null;
1882 sess = VamsasApplication.getSessionList();
1883 } catch (Exception e)
1885 jalview.bin.Cache.log.warn(
1886 "Problem getting current sessions list.", e);
1891 jalview.bin.Cache.log.debug("Got current sessions list: "
1892 + sess.length + " entries.");
1893 VamsasStMenu.removeAll();
1894 for (int i = 0; i < sess.length; i++)
1896 JMenuItem sessit = new JMenuItem();
1897 sessit.setText(sess[i]);
1898 sessit.setToolTipText("Connect to session " + sess[i]);
1899 final Desktop dsktp = this;
1900 final String mysesid = sess[i];
1901 sessit.addActionListener(new ActionListener()
1904 public void actionPerformed(ActionEvent e)
1906 if (dsktp.v_client == null)
1908 Thread rthr = new Thread(new Runnable()
1913 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1914 dsktp.setupVamsasConnectedGui();
1915 dsktp.v_client.initial_update();
1923 VamsasStMenu.add(sessit);
1925 // don't show an empty menu.
1926 VamsasStMenu.setVisible(sess.length > 0);
1931 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1932 VamsasStMenu.removeAll();
1933 VamsasStMenu.setVisible(false);
1938 // Not interested in the content. Just hide ourselves.
1939 VamsasStMenu.setVisible(false);
1943 public void vamsasSave_actionPerformed(ActionEvent e)
1945 if (v_client != null)
1947 JalviewFileChooser chooser = new JalviewFileChooser(
1948 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1949 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1951 { "Vamsas Document" }, "Vamsas Document");
1953 chooser.setFileView(new JalviewFileView());
1954 chooser.setDialogTitle("Save Vamsas Document Archive");
1956 int value = chooser.showSaveDialog(this);
1958 if (value == JalviewFileChooser.APPROVE_OPTION)
1960 java.io.File choice = chooser.getSelectedFile();
1961 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1962 + choice.getName());
1963 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1964 String warnmsg = null;
1965 String warnttl = null;
1968 v_client.vclient.storeDocument(choice);
1971 warnttl = "Serious Problem saving Vamsas Document";
1972 warnmsg = ex.toString();
1973 jalview.bin.Cache.log.error("Error Whilst saving document to "
1976 } catch (Exception ex)
1978 warnttl = "Problem saving Vamsas Document.";
1979 warnmsg = ex.toString();
1980 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1984 removeProgressPanel(progpanel);
1985 if (warnmsg != null)
1987 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1989 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1995 JPanel vamUpdate = null;
1998 * hide vamsas user gui bits when a vamsas document event is being handled.
2001 * true to hide gui, false to reveal gui
2003 public void setVamsasUpdate(boolean b)
2005 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2006 + (b ? "in progress" : "finished"));
2008 if (vamUpdate != null)
2010 this.removeProgressPanel(vamUpdate);
2014 vamUpdate = this.addProgressPanel("Updating vamsas session");
2016 vamsasStart.setVisible(!b);
2017 vamsasStop.setVisible(!b);
2018 vamsasSave.setVisible(!b);
2021 public JInternalFrame[] getAllFrames()
2023 return desktop.getAllFrames();
2027 * Checks the given url to see if it gives a response indicating that the user
2028 * should be informed of a new questionnaire.
2032 public void checkForQuestionnaire(String url)
2034 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2035 // javax.swing.SwingUtilities.invokeLater(jvq);
2036 new Thread(jvq).start();
2040 * Proxy class for JDesktopPane which optionally displays the current memory
2041 * usage and highlights the desktop area with a red bar if free memory runs
2046 public class MyDesktopPane extends JDesktopPane implements Runnable
2049 boolean showMemoryUsage = false;
2053 java.text.NumberFormat df;
2055 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2058 public MyDesktopPane(boolean showMemoryUsage)
2060 showMemoryUsage(showMemoryUsage);
2063 public void showMemoryUsage(boolean showMemoryUsage)
2065 this.showMemoryUsage = showMemoryUsage;
2066 if (showMemoryUsage)
2068 Thread worker = new Thread(this);
2073 public boolean isShowMemoryUsage()
2075 return showMemoryUsage;
2080 df = java.text.NumberFormat.getNumberInstance();
2081 df.setMaximumFractionDigits(2);
2082 runtime = Runtime.getRuntime();
2084 while (showMemoryUsage)
2088 maxMemory = runtime.maxMemory() / 1048576f;
2089 allocatedMemory = runtime.totalMemory() / 1048576f;
2090 freeMemory = runtime.freeMemory() / 1048576f;
2091 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2093 percentUsage = (totalFreeMemory / maxMemory) * 100;
2095 // if (percentUsage < 20)
2097 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2099 // instance.set.setBorder(border1);
2102 // sleep after showing usage
2104 } catch (Exception ex)
2106 ex.printStackTrace();
2111 public void paintComponent(Graphics g)
2113 if (showMemoryUsage && g != null && df != null)
2115 if (percentUsage < 20)
2116 g.setColor(Color.red);
2117 FontMetrics fm = g.getFontMetrics();
2121 "Total Free Memory: " + df.format(totalFreeMemory)
2122 + "MB; Max Memory: " + df.format(maxMemory)
2123 + "MB; " + df.format(percentUsage) + "%", 10,
2124 getHeight() - fm.getHeight());
2131 * fixes stacking order after a modal dialog to ensure windows that should be on top actually are
2133 public void relayerWindows()
2138 protected JMenuItem groovyShell;
2140 public void doGroovyCheck()
2142 if (jalview.bin.Cache.groovyJarsPresent())
2144 groovyShell = new JMenuItem();
2145 groovyShell.setText("Groovy Console...");
2146 groovyShell.addActionListener(new ActionListener()
2148 public void actionPerformed(ActionEvent e)
2150 groovyShell_actionPerformed(e);
2153 toolsMenu.add(groovyShell);
2154 groovyShell.setVisible(true);
2159 * Accessor method to quickly get all the AlignmentFrames loaded.
2161 public static AlignFrame[] getAlignframes()
2163 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2169 Vector avp = new Vector();
2173 for (int i = frames.length - 1; i > -1; i--)
2175 if (frames[i] instanceof AlignFrame)
2177 AlignFrame af = (AlignFrame) frames[i];
2181 } catch (Exception ex)
2183 ex.printStackTrace();
2185 if (avp.size() == 0)
2189 AlignFrame afs[] = new AlignFrame[avp.size()];
2190 for (int i = 0, j = avp.size(); i < j; i++)
2192 afs[i] = (AlignFrame) avp.elementAt(i);
2197 public AppJmol[] getJmols()
2199 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2205 Vector avp = new Vector();
2209 for (int i = frames.length - 1; i > -1; i--)
2211 if (frames[i] instanceof AppJmol)
2213 AppJmol af = (AppJmol) frames[i];
2217 } catch (Exception ex)
2219 ex.printStackTrace();
2221 if (avp.size() == 0)
2225 AppJmol afs[] = new AppJmol[avp.size()];
2226 for (int i = 0, j = avp.size(); i < j; i++)
2228 afs[i] = (AppJmol) avp.elementAt(i);
2235 * Add Groovy Support to Jalview
2237 public void groovyShell_actionPerformed(ActionEvent e)
2239 // use reflection to avoid creating compilation dependency.
2240 if (!jalview.bin.Cache.groovyJarsPresent())
2243 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2247 Class gcClass = Desktop.class.getClassLoader().loadClass(
2248 "groovy.ui.Console");
2249 Constructor gccons = gcClass.getConstructor(null);
2250 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2252 { String.class, Object.class });
2253 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2254 Object gc = gccons.newInstance(null);
2255 setvar.invoke(gc, new Object[]
2256 { "Jalview", this });
2257 run.invoke(gc, null);
2258 } catch (Exception ex)
2260 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2262 .showInternalMessageDialog(
2265 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2266 "Jalview Groovy Support Failed",
2267 JOptionPane.ERROR_MESSAGE);
2272 * Progress bars managed by the IProgressIndicator method.
2274 private Hashtable<Long,JPanel> progressBars;
2275 private Hashtable<Long,IProgressIndicatorHandler> progressBarHandlers;
2280 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2282 public void setProgressBar(String message, long id)
2284 if (progressBars == null)
2286 progressBars = new Hashtable<Long,JPanel>();
2287 progressBarHandlers = new Hashtable<Long,IProgressIndicatorHandler>();
2290 if (progressBars.get(new Long(id)) != null)
2292 JPanel progressPanel = progressBars
2293 .remove(new Long(id));
2294 if (progressBarHandlers.contains(new Long(id)))
2296 progressBarHandlers.remove(new Long(id));
2298 removeProgressPanel(progressPanel);
2302 progressBars.put(new Long(id), addProgressPanel(message));
2309 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2310 * jalview.gui.IProgressIndicatorHandler)
2312 public void registerHandler(final long id,
2313 final IProgressIndicatorHandler handler)
2315 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2318 "call setProgressBar before registering the progress bar's handler.");
2320 progressBarHandlers.put(new Long(id), handler);
2321 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2322 if (handler.canCancel())
2324 JButton cancel = new JButton("Cancel");
2325 final IProgressIndicator us = this;
2326 cancel.addActionListener(new ActionListener()
2329 public void actionPerformed(ActionEvent e)
2331 handler.cancelActivity(id);
2334 + ((JLabel) progressPanel.getComponent(0))
2338 progressPanel.add(cancel, BorderLayout.EAST);
2344 * @return true if any progress bars are still active
2347 public boolean operationInProgress()
2349 if (progressBars != null && progressBars.size() > 0)
2357 * This will return the first AlignFrame viewing AlignViewport av. It will
2358 * break if there are more than one AlignFrames viewing a particular av. This
2361 * @return alignFrame for av
2363 public static AlignFrame getAlignFrameFor(AlignViewport av)
2365 if (desktop != null)
2367 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2368 for (int panel = 0; aps != null && panel < aps.length; panel++)
2370 if (aps[panel] != null && aps[panel].av == av)
2372 return aps[panel].alignFrame;
2379 public VamsasApplication getVamsasApplication()
2386 * flag set if jalview GUI is being operated programmatically
2388 private boolean inBatchMode = false;
2391 * check if jalview GUI is being operated programmatically
2393 * @return inBatchMode
2395 public boolean isInBatchMode()
2401 * set flag if jalview GUI is being operated programmatically
2403 * @param inBatchMode
2405 public void setInBatchMode(boolean inBatchMode)
2407 this.inBatchMode = inBatchMode;
2410 public void startServiceDiscovery()
2412 startServiceDiscovery(false);
2415 public void startServiceDiscovery(boolean blocking)
2417 boolean alive = true;
2418 Thread t0 = null, t1 = null, t2 = null;
2420 // todo: changesupport handlers need to be transferred
2421 if (discoverer == null)
2423 discoverer = new jalview.ws.jws1.Discoverer();
2424 // register PCS handler for desktop.
2425 discoverer.addPropertyChangeListener(changeSupport);
2427 // JAL-940 - disabled JWS1 service configuration - always start discoverer until we phase out completely
2430 (t0 = new Thread(discoverer)).start();
2435 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2437 // EnfinEnvision web service menu entries are rebuild every time the
2438 // menu is shown, so no changeSupport events are needed.
2439 jalview.ws.EnfinEnvision2OneWay.getInstance();
2440 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2443 } catch (Exception e)
2446 .info("Exception when trying to launch Envision2 workflow discovery.",
2448 Cache.log.info(e.getStackTrace());
2450 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2452 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2454 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2456 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2462 // TODO: do rest service discovery
2471 } catch (Exception e)
2474 alive = (t1 != null && t1.isAlive())
2475 || (t2 != null && t2.isAlive())
2476 || (t3 != null && t3.isAlive())
2477 || (t0 != null && t0.isAlive());
2483 * called to check if the service discovery process completed successfully.
2487 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2489 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2491 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2492 .getErrorMessages();
2495 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2497 if (serviceChangedDialog == null)
2499 // only run if we aren't already displaying one of these.
2500 javax.swing.SwingUtilities
2501 .invokeLater(serviceChangedDialog = new Runnable()
2507 .showInternalMessageDialog(
2510 + "It may be that you have invalid JABA URLs\nin your web service preferences.\n\nGo to the Web services tab of the\nTools->Preferences dialog box to change them.\n",
2511 "Preferences Problem",
2512 JOptionPane.WARNING_MESSAGE);
2513 serviceChangedDialog = null;
2522 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2529 private Runnable serviceChangedDialog = null;
2532 * start a thread to open a URL in the configured browser. Pops up a warning
2533 * dialog to the user if there is an exception when calling out to the browser
2538 public static void showUrl(final String url)
2540 showUrl(url, Desktop.instance);
2543 * Like showUrl but allows progress handler to be specified
2545 * @param progress (null) or object implementing IProgressIndicator
2547 public static void showUrl(final String url, final IProgressIndicator progress)
2549 new Thread(new Runnable()
2555 if (progress!=null) {
2556 progress.setProgressBar("Opening "+url, this.hashCode());
2558 jalview.util.BrowserLauncher.openURL(url);
2559 } catch (Exception ex)
2562 .showInternalMessageDialog(
2564 "Unixers: Couldn't find default web browser."
2565 + "\nAdd the full path to your browser in Preferences.",
2566 "Web browser not found",
2567 JOptionPane.WARNING_MESSAGE);
2569 ex.printStackTrace();
2571 if (progress!=null) {
2572 progress.setProgressBar(null, this.hashCode());
2578 public static WsParamSetManager wsparamManager = null;
2580 public static ParamManager getUserParameterStore()
2582 if (wsparamManager == null)
2584 wsparamManager = new WsParamSetManager();
2586 return wsparamManager;
2590 * static hyperlink handler proxy method for use by Jalview's internal windows
2593 public static void hyperlinkUpdate(HyperlinkEvent e)
2595 if (e.getEventType() == EventType.ACTIVATED)
2600 url = e.getURL().toString();
2601 Desktop.showUrl(url);
2602 } catch (Exception x)
2605 if (Cache.log!=null) {
2606 Cache.log.error("Couldn't handle string "+url+" as a URL.");
2608 System.err.println("Couldn't handle string "+url+" as a URL.");
2611 // ignore any exceptions due to dud links.
2617 * single thread that handles display of dialogs to user.
2619 ExecutorService dialogExecutor=null;
2622 * add another dialog thread to the queue
2625 public synchronized void addDialogThread(Runnable prompter)
2627 if (dialogExecutor==null)
2629 dialogExecutor = Executors.newSingleThreadExecutor();
2631 dialogExecutor.submit(prompter);