2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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;
69 import java.util.concurrent.Semaphore;
71 import javax.swing.DefaultDesktopManager;
72 import javax.swing.DesktopManager;
73 import javax.swing.JButton;
74 import javax.swing.JComboBox;
75 import javax.swing.JComponent;
76 import javax.swing.JDesktopPane;
77 import javax.swing.JFrame;
78 import javax.swing.JInternalFrame;
79 import javax.swing.JLabel;
80 import javax.swing.JMenuItem;
81 import javax.swing.JOptionPane;
82 import javax.swing.JPanel;
83 import javax.swing.JPopupMenu;
84 import javax.swing.JProgressBar;
85 import javax.swing.SwingUtilities;
86 import javax.swing.event.HyperlinkEvent;
87 import javax.swing.event.MenuEvent;
88 import javax.swing.event.MenuListener;
89 import javax.swing.event.HyperlinkEvent.EventType;
96 * @version $Revision: 1.155 $
98 public class Desktop extends jalview.jbgui.GDesktop implements
99 DropTargetListener, ClipboardOwner, IProgressIndicator,
100 jalview.api.StructureSelectionManagerProvider
103 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
106 * news reader - null if it was never started.
108 private BlogReader jvnews = null;
112 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
114 public void addJalviewPropertyChangeListener(
115 PropertyChangeListener listener)
117 changeSupport.addJalviewPropertyChangeListener(listener);
121 * @param propertyName
123 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
124 * java.beans.PropertyChangeListener)
126 public void addJalviewPropertyChangeListener(String propertyName,
127 PropertyChangeListener listener)
129 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
133 * @param propertyName
135 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
136 * java.beans.PropertyChangeListener)
138 public void removeJalviewPropertyChangeListener(String propertyName,
139 PropertyChangeListener listener)
141 changeSupport.removeJalviewPropertyChangeListener(propertyName,
145 /** Singleton Desktop instance */
146 public static Desktop instance;
148 public static MyDesktopPane desktop;
150 static int openFrameCount = 0;
152 static final int xOffset = 30;
154 static final int yOffset = 30;
156 public static jalview.ws.jws1.Discoverer discoverer;
158 public static Object[] jalviewClipboard;
160 public static boolean internalCopy = false;
162 static int fileLoadingCount = 0;
164 class MyDesktopManager implements DesktopManager
167 private DesktopManager delegate;
169 public MyDesktopManager(DesktopManager delegate)
171 this.delegate = delegate;
174 public void activateFrame(JInternalFrame f)
178 delegate.activateFrame(f);
179 } catch (NullPointerException npe)
181 Point p = getMousePosition();
182 instance.showPasteMenu(p.x, p.y);
186 public void beginDraggingFrame(JComponent f)
188 delegate.beginDraggingFrame(f);
191 public void beginResizingFrame(JComponent f, int direction)
193 delegate.beginResizingFrame(f, direction);
196 public void closeFrame(JInternalFrame f)
198 delegate.closeFrame(f);
201 public void deactivateFrame(JInternalFrame f)
203 delegate.deactivateFrame(f);
206 public void deiconifyFrame(JInternalFrame f)
208 delegate.deiconifyFrame(f);
211 public void dragFrame(JComponent f, int newX, int newY)
217 delegate.dragFrame(f, newX, newY);
220 public void endDraggingFrame(JComponent f)
222 delegate.endDraggingFrame(f);
225 public void endResizingFrame(JComponent f)
227 delegate.endResizingFrame(f);
230 public void iconifyFrame(JInternalFrame f)
232 delegate.iconifyFrame(f);
235 public void maximizeFrame(JInternalFrame f)
237 delegate.maximizeFrame(f);
240 public void minimizeFrame(JInternalFrame f)
242 delegate.minimizeFrame(f);
245 public void openFrame(JInternalFrame f)
247 delegate.openFrame(f);
250 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
253 Rectangle b = desktop.getBounds();
258 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
261 public void setBoundsForFrame(JComponent f, int newX, int newY,
262 int newWidth, int newHeight)
264 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
267 // All other methods, simply delegate
272 * Creates a new Desktop object.
277 * A note to implementors. It is ESSENTIAL that any activities that might
278 * block are spawned off as threads rather than waited for during this
282 doVamsasClientCheck();
285 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
286 setDefaultCloseOperation(!jalview.bin.Cache.isPlugin() ? JFrame.EXIT_ON_CLOSE : JFrame.DISPOSE_ON_CLOSE);
287 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
289 boolean showjconsole = jalview.bin.Cache.getDefault(
290 "SHOW_JAVA_CONSOLE", false);
291 desktop = new MyDesktopPane(selmemusage);
292 showMemusage.setSelected(selmemusage);
293 desktop.setBackground(Color.white);
294 getContentPane().setLayout(new BorderLayout());
295 // alternate config - have scrollbars - see notes in JAL-153
296 // JScrollPane sp = new JScrollPane();
297 // sp.getViewport().setView(desktop);
298 // getContentPane().add(sp, BorderLayout.CENTER);
299 getContentPane().add(desktop, BorderLayout.CENTER);
300 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
302 // This line prevents Windows Look&Feel resizing all new windows to maximum
303 // if previous window was maximised
304 desktop.setDesktopManager(new MyDesktopManager(
305 new DefaultDesktopManager()));
307 Rectangle dims = getLastKnownDimensions("");
314 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
315 setBounds((int) (screenSize.width - 900) / 2,
316 (int) (screenSize.height - 650) / 2, 900, 650);
318 jconsole = new Console(this, showjconsole);
319 // add essential build information
320 jconsole.setHeader("Jalview Desktop "
321 + jalview.bin.Cache.getProperty("VERSION") + "\n"
323 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
324 + "Java version: " + System.getProperty("java.version") + "\n"
325 + System.getProperty("os.arch") + " "
326 + System.getProperty("os.name") + " "
327 + System.getProperty("os.version"));
329 showConsole(showjconsole);
331 showNews.setVisible(false);
333 this.addWindowListener(new WindowAdapter()
335 public void windowClosing(WindowEvent evt)
342 this.addMouseListener(ma = new MouseAdapter()
344 public void mousePressed(MouseEvent evt)
346 if (SwingUtilities.isRightMouseButton(evt))
348 showPasteMenu(evt.getX(), evt.getY());
352 desktop.addMouseListener(ma);
354 this.addFocusListener(new FocusListener()
358 public void focusLost(FocusEvent e)
360 // TODO Auto-generated method stub
365 public void focusGained(FocusEvent e)
367 Cache.log.debug("Relaying windows after focus gain");
368 // make sure that we sort windows properly after we gain focus
369 instance.relayerWindows();
372 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
373 // Spawn a thread that shows the splashscreen
374 SwingUtilities.invokeLater(new Runnable()
383 // Thread off a new instance of the file chooser - this reduces the time it
384 // takes to open it later on.
385 new Thread(new Runnable()
389 Cache.log.debug("Filechooser init thread started.");
390 JalviewFileChooser chooser = new JalviewFileChooser(
391 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
392 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
393 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
394 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
395 Cache.log.debug("Filechooser init thread finished.");
398 // Add the service change listener
399 changeSupport.addJalviewPropertyChangeListener("services",
400 new PropertyChangeListener()
404 public void propertyChange(PropertyChangeEvent evt)
406 Cache.log.debug("Firing service changed event for "
407 + evt.getNewValue());
408 JalviewServicesChanged(evt);
414 public void checkForNews()
416 final Desktop me = this;
417 // Thread off the news reader, in case there are connection problems.
418 addDialogThread(new Runnable()
423 Cache.log.debug("Starting news thread.");
425 jvnews = new BlogReader(me);
426 showNews.setVisible(true);
427 Cache.log.debug("Completed news thread.");
432 protected void showNews_actionPerformed(ActionEvent e)
434 showNews(showNews.isSelected());
437 void showNews(boolean visible)
440 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
441 showNews.setSelected(visible);
442 if (visible && !jvnews.isVisible())
444 new Thread(new Runnable()
449 long instance = System.currentTimeMillis();
450 Desktop.instance.setProgressBar("Refreshing news", instance);
451 jvnews.refreshNews();
452 Desktop.instance.setProgressBar(null, instance);
461 * recover the last known dimensions for a jalview window
464 * - empty string is desktop, all other windows have unique prefix
465 * @return null or last known dimensions scaled to current geometry (if last
466 * window geom was known)
468 Rectangle getLastKnownDimensions(String windowName)
470 // TODO: lock aspect ratio for scaling desktop Bug #0058199
471 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
472 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
473 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
474 String width = jalview.bin.Cache.getProperty(windowName
476 String height = jalview.bin.Cache.getProperty(windowName
478 if ((x != null) && (y != null) && (width != null) && (height != null))
480 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
481 .parseInt(width), ih = Integer.parseInt(height);
482 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
484 // attempt #1 - try to cope with change in screen geometry - this
485 // version doesn't preserve original jv aspect ratio.
486 // take ratio of current screen size vs original screen size.
487 double sw = ((1f * screenSize.width) / (1f * Integer
488 .parseInt(jalview.bin.Cache
489 .getProperty("SCREENGEOMETRY_WIDTH"))));
490 double sh = ((1f * screenSize.height) / (1f * Integer
491 .parseInt(jalview.bin.Cache
492 .getProperty("SCREENGEOMETRY_HEIGHT"))));
493 // rescale the bounds depending upon the current screen geometry.
494 ix = (int) (ix * sw);
495 iw = (int) (iw * sw);
496 iy = (int) (iy * sh);
497 ih = (int) (ih * sh);
498 while (ix >= screenSize.width)
500 jalview.bin.Cache.log
501 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
502 ix -= screenSize.width;
504 while (iy >= screenSize.height)
506 jalview.bin.Cache.log
507 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
508 iy -= screenSize.height;
510 jalview.bin.Cache.log.debug("Got last known dimensions for "
511 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
514 // return dimensions for new instance
515 return new Rectangle(ix, iy, iw, ih);
520 private void doVamsasClientCheck()
522 if (jalview.bin.Cache.vamsasJarsPresent())
524 setupVamsasDisconnectedGui();
525 VamsasMenu.setVisible(true);
526 final Desktop us = this;
527 VamsasMenu.addMenuListener(new MenuListener()
529 // this listener remembers when the menu was first selected, and
530 // doesn't rebuild the session list until it has been cleared and
532 boolean refresh = true;
534 public void menuCanceled(MenuEvent e)
539 public void menuDeselected(MenuEvent e)
544 public void menuSelected(MenuEvent e)
548 us.buildVamsasStMenu();
553 vamsasStart.setVisible(true);
557 void showPasteMenu(int x, int y)
559 JPopupMenu popup = new JPopupMenu();
560 JMenuItem item = new JMenuItem("Paste To New Window");
561 item.addActionListener(new ActionListener()
563 public void actionPerformed(ActionEvent evt)
570 popup.show(this, x, y);
577 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
578 Transferable contents = c.getContents(this);
580 if (contents != null)
582 String file = (String) contents
583 .getTransferData(DataFlavor.stringFlavor);
585 String format = new IdentifyFile().Identify(file,
586 FormatAdapter.PASTE);
588 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
591 } catch (Exception ex)
594 .println("Unable to paste alignment from system clipboard:\n"
600 * Adds and opens the given frame to the desktop
611 public static synchronized void addInternalFrame(
612 final JInternalFrame frame, String title, int w, int h)
614 addInternalFrame(frame, title, w, h, true);
631 public static synchronized void addInternalFrame(
632 final JInternalFrame frame, String title, int w, int h,
636 // TODO: allow callers to determine X and Y position of frame (eg. via
638 // TODO: consider fixing method to update entries in the window submenu with
639 // the current window title
641 frame.setTitle(title);
642 if (frame.getWidth() < 1 || frame.getHeight() < 1)
646 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
647 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
648 // IF JALVIEW IS RUNNING HEADLESS
649 // ///////////////////////////////////////////////
650 if (System.getProperty("java.awt.headless") != null
651 && System.getProperty("java.awt.headless").equals("true"))
658 frame.setVisible(true);
659 frame.setClosable(true);
660 frame.setResizable(resizable);
661 frame.setMaximizable(resizable);
662 frame.setIconifiable(resizable);
663 frame.setFrameIcon(null);
665 if (frame.getX() < 1 && frame.getY() < 1)
667 frame.setLocation(xOffset * openFrameCount, yOffset
668 * ((openFrameCount - 1) % 10) + yOffset);
671 final JMenuItem menuItem = new JMenuItem(title);
672 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
674 public void internalFrameActivated(
675 javax.swing.event.InternalFrameEvent evt)
677 JInternalFrame itf = desktop.getSelectedFrame();
685 public void internalFrameClosed(
686 javax.swing.event.InternalFrameEvent evt)
688 PaintRefresher.RemoveComponent(frame);
690 windowMenu.remove(menuItem);
691 JInternalFrame itf = desktop.getSelectedFrame();
700 menuItem.addActionListener(new ActionListener()
702 public void actionPerformed(ActionEvent e)
706 frame.setSelected(true);
707 frame.setIcon(false);
708 } catch (java.beans.PropertyVetoException ex)
714 menuItem.addMouseListener(new MouseListener()
718 public void mouseReleased(MouseEvent e)
723 public void mousePressed(MouseEvent e)
728 public void mouseExited(MouseEvent e)
732 frame.setSelected(false);
733 } catch (PropertyVetoException e1)
739 public void mouseEntered(MouseEvent e)
743 frame.setSelected(true);
744 } catch (PropertyVetoException e1)
750 public void mouseClicked(MouseEvent e)
756 windowMenu.add(menuItem);
762 frame.setSelected(true);
763 frame.requestFocus();
764 } catch (java.beans.PropertyVetoException ve)
766 } catch (java.lang.ClassCastException cex)
769 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
774 public void lostOwnership(Clipboard clipboard, Transferable contents)
778 Desktop.jalviewClipboard = null;
781 internalCopy = false;
784 public void dragEnter(DropTargetDragEvent evt)
788 public void dragExit(DropTargetEvent evt)
792 public void dragOver(DropTargetDragEvent evt)
796 public void dropActionChanged(DropTargetDragEvent evt)
806 public void drop(DropTargetDropEvent evt)
808 Transferable t = evt.getTransferable();
809 java.util.List files = null;
810 java.util.List protocols = null;
814 DataFlavor uriListFlavor = new DataFlavor(
815 "text/uri-list;class=java.lang.String");
816 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
818 // Works on Windows and MacOSX
819 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
820 files = (java.util.List) t
821 .getTransferData(DataFlavor.javaFileListFlavor);
823 else if (t.isDataFlavorSupported(uriListFlavor))
825 // This is used by Unix drag system
826 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
827 String data = (String) t.getTransferData(uriListFlavor);
828 files = new java.util.ArrayList(1);
829 protocols = new java.util.ArrayList(1);
830 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
831 data, "\r\n"); st.hasMoreTokens();)
833 String s = st.nextToken();
834 if (s.startsWith("#"))
836 // the line is a comment (as per the RFC 2483)
839 java.net.URI uri = new java.net.URI(s);
840 if (uri.getScheme().toLowerCase().startsWith("http"))
842 protocols.add(FormatAdapter.URL);
843 files.add(uri.toString());
847 // otherwise preserve old behaviour: catch all for file objects
848 java.io.File file = new java.io.File(uri);
849 protocols.add(FormatAdapter.FILE);
850 files.add(file.toString());
854 } catch (Exception e)
862 for (int i = 0; i < files.size(); i++)
864 String file = files.get(i).toString();
865 String protocol = (protocols == null) ? FormatAdapter.FILE
866 : (String) protocols.get(i);
867 String format = null;
869 if (file.endsWith(".jar"))
876 format = new IdentifyFile().Identify(file, protocol);
879 new FileLoader().LoadFile(file, protocol, format);
882 } catch (Exception ex)
894 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
896 JalviewFileChooser chooser = new JalviewFileChooser(
897 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
898 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
899 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
900 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
902 chooser.setFileView(new JalviewFileView());
903 chooser.setDialogTitle("Open local file");
904 chooser.setToolTipText("Open");
906 int value = chooser.showOpenDialog(this);
908 if (value == JalviewFileChooser.APPROVE_OPTION)
910 String choice = chooser.getSelectedFile().getPath();
911 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
912 .getSelectedFile().getParent());
914 String format = null;
915 if (chooser.getSelectedFormat().equals("Jalview"))
921 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
924 if (viewport != null)
926 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
931 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
942 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
944 // This construct allows us to have a wider textfield
946 JLabel label = new JLabel("Enter URL of Input File");
947 final JComboBox history = new JComboBox();
949 JPanel panel = new JPanel(new GridLayout(2, 1));
952 history.setPreferredSize(new Dimension(400, 20));
953 history.setEditable(true);
954 history.addItem("http://www.");
956 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
960 if (historyItems != null)
962 st = new StringTokenizer(historyItems, "\t");
964 while (st.hasMoreTokens())
966 history.addItem(st.nextElement());
970 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
971 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
973 if (reply != JOptionPane.OK_OPTION)
978 String url = history.getSelectedItem().toString();
980 if (url.toLowerCase().endsWith(".jar"))
982 if (viewport != null)
984 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
989 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
994 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
996 if (format.equals("URL NOT FOUND"))
998 JOptionPane.showInternalMessageDialog(Desktop.desktop,
999 "Couldn't locate " + url, "URL not found",
1000 JOptionPane.WARNING_MESSAGE);
1005 if (viewport != null)
1007 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1011 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1022 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1024 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1025 cap.setForInput(viewport);
1026 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1034 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1036 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1037 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1039 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1040 getBounds().y, getWidth(), getHeight()));
1042 if (jconsole != null)
1044 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1045 jconsole.stopConsole();
1049 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1052 if (dialogExecutor != null)
1054 dialogExecutor.shutdownNow();
1057 if (!jalview.bin.Cache.isPlugin()) {
1065 private void storeLastKnownDimensions(String string, Rectangle jc)
1067 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1068 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1069 + " height:" + jc.height);
1071 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1072 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1073 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1074 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1083 public void aboutMenuItem_actionPerformed(ActionEvent e)
1085 // StringBuffer message = getAboutMessage(false);
1086 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1088 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1089 new Thread(new Runnable()
1093 new SplashScreen(true);
1098 public StringBuffer getAboutMessage(boolean shortv)
1100 StringBuffer message = new StringBuffer();
1101 message.append("<html>");
1104 message.append("<h1><strong>Version: "
1105 + jalview.bin.Cache.getProperty("VERSION")
1106 + "</strong></h1><br>");
1107 message.append("<strong>Last Updated: <em>"
1108 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1109 + "</em></strong>");
1115 message.append("<strong>Version "
1116 + jalview.bin.Cache.getProperty("VERSION")
1117 + "; last updated: "
1118 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1121 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1124 message.append("<br>...Checking latest version...</br>");
1126 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1127 .equals(jalview.bin.Cache.getProperty("VERSION")))
1129 boolean red = false;
1130 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1131 .indexOf("automated build") == -1)
1134 // Displayed when code version and jnlp version do not match and code
1135 // version is not a development build
1136 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1139 message.append("<br>!! Version "
1140 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1142 + " is available for download from "
1143 + jalview.bin.Cache.getDefault("www.jalview.org",
1144 "http://www.jalview.org") + " !!");
1147 message.append("</div>");
1150 message.append("<br>Authors: "
1154 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1155 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1156 + "<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"
1157 + "<br>If you use Jalview, please cite:"
1158 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1159 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1160 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1171 public void documentationMenuItem_actionPerformed(ActionEvent e)
1175 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1176 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1177 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1179 javax.help.HelpBroker hb = hs.createHelpBroker();
1180 hb.setCurrentID("home");
1181 hb.setDisplayed(true);
1182 } catch (Exception ex)
1187 public void closeAll_actionPerformed(ActionEvent e)
1189 JInternalFrame[] frames = desktop.getAllFrames();
1190 for (int i = 0; i < frames.length; i++)
1194 frames[i].setClosed(true);
1195 } catch (java.beans.PropertyVetoException ex)
1199 System.out.println("ALL CLOSED");
1200 if (v_client != null)
1202 // TODO clear binding to vamsas document objects on close_all
1207 public void raiseRelated_actionPerformed(ActionEvent e)
1209 reorderAssociatedWindows(false, false);
1212 public void minimizeAssociated_actionPerformed(ActionEvent e)
1214 reorderAssociatedWindows(true, false);
1217 void closeAssociatedWindows()
1219 reorderAssociatedWindows(false, true);
1225 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1228 protected void garbageCollect_actionPerformed(ActionEvent e)
1230 // We simply collect the garbage
1231 jalview.bin.Cache.log.debug("Collecting garbage...");
1233 jalview.bin.Cache.log.debug("Finished garbage collection.");
1240 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1243 protected void showMemusage_actionPerformed(ActionEvent e)
1245 desktop.showMemoryUsage(showMemusage.isSelected());
1252 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1255 protected void showConsole_actionPerformed(ActionEvent e)
1257 showConsole(showConsole.isSelected());
1260 Console jconsole = null;
1263 * control whether the java console is visible or not
1267 void showConsole(boolean selected)
1269 showConsole.setSelected(selected);
1270 // TODO: decide if we should update properties file
1271 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1273 jconsole.setVisible(selected);
1276 void reorderAssociatedWindows(boolean minimize, boolean close)
1278 JInternalFrame[] frames = desktop.getAllFrames();
1279 if (frames == null || frames.length < 1)
1284 AlignViewport source = null, target = null;
1285 if (frames[0] instanceof AlignFrame)
1287 source = ((AlignFrame) frames[0]).getCurrentView();
1289 else if (frames[0] instanceof TreePanel)
1291 source = ((TreePanel) frames[0]).getViewPort();
1293 else if (frames[0] instanceof PCAPanel)
1295 source = ((PCAPanel) frames[0]).av;
1297 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1299 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1304 for (int i = 0; i < frames.length; i++)
1307 if (frames[i] == null)
1311 if (frames[i] instanceof AlignFrame)
1313 target = ((AlignFrame) frames[i]).getCurrentView();
1315 else if (frames[i] instanceof TreePanel)
1317 target = ((TreePanel) frames[i]).getViewPort();
1319 else if (frames[i] instanceof PCAPanel)
1321 target = ((PCAPanel) frames[i]).av;
1323 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1325 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1328 if (source == target)
1334 frames[i].setClosed(true);
1338 frames[i].setIcon(minimize);
1341 frames[i].toFront();
1345 } catch (java.beans.PropertyVetoException ex)
1359 protected void preferences_actionPerformed(ActionEvent e)
1370 public void saveState_actionPerformed(ActionEvent e)
1372 JalviewFileChooser chooser = new JalviewFileChooser(
1373 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1374 { "jar" }, new String[]
1375 { "Jalview Project" }, "Jalview Project");
1377 chooser.setFileView(new JalviewFileView());
1378 chooser.setDialogTitle("Save State");
1380 int value = chooser.showSaveDialog(this);
1382 if (value == JalviewFileChooser.APPROVE_OPTION)
1384 final Desktop me = this;
1385 final java.io.File choice = chooser.getSelectedFile();
1386 new Thread(new Runnable()
1391 setProgressBar("Saving jalview project " + choice.getName(),
1393 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1394 choice.getParent());
1395 // TODO catch and handle errors for savestate
1396 // TODO prevent user from messing with the Desktop whilst we're saving
1399 new Jalview2XML().SaveState(choice);
1400 } catch (OutOfMemoryError oom)
1402 new OOMWarning("Whilst saving current state to "
1403 + choice.getName(), oom);
1404 } catch (Exception ex)
1407 "Problems whilst trying to save to " + choice.getName(),
1409 JOptionPane.showMessageDialog(
1411 "Error whilst saving current state to "
1412 + choice.getName(), "Couldn't save project",
1413 JOptionPane.WARNING_MESSAGE);
1415 setProgressBar(null, choice.hashCode());
1427 public void loadState_actionPerformed(ActionEvent e)
1429 JalviewFileChooser chooser = new JalviewFileChooser(
1430 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1431 { "jar" }, new String[]
1432 { "Jalview Project" }, "Jalview Project");
1433 chooser.setFileView(new JalviewFileView());
1434 chooser.setDialogTitle("Restore state");
1436 int value = chooser.showOpenDialog(this);
1438 if (value == JalviewFileChooser.APPROVE_OPTION)
1440 final String choice = chooser.getSelectedFile().getAbsolutePath();
1441 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1442 .getSelectedFile().getParent());
1443 new Thread(new Runnable()
1447 setProgressBar("loading jalview project " + choice,
1451 new Jalview2XML().LoadJalviewAlign(choice);
1452 } catch (OutOfMemoryError oom)
1454 new OOMWarning("Whilst loading project from " + choice, oom);
1455 } catch (Exception ex)
1457 Cache.log.error("Problems whilst loading project from "
1459 JOptionPane.showMessageDialog(Desktop.desktop,
1460 "Error whilst loading project from " + choice,
1461 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1463 setProgressBar(null, choice.hashCode());
1469 public void inputSequence_actionPerformed(ActionEvent e)
1471 new SequenceFetcher(this);
1474 JPanel progressPanel;
1476 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1478 public void startLoading(final String fileName)
1480 if (fileLoadingCount == 0)
1482 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1488 private JPanel addProgressPanel(String string)
1490 if (progressPanel == null)
1492 progressPanel = new JPanel(new GridLayout(1, 1));
1493 totalProgressCount = 0;
1494 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1496 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1497 JProgressBar progressBar = new JProgressBar();
1498 progressBar.setIndeterminate(true);
1500 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1502 thisprogress.add(progressBar, BorderLayout.CENTER);
1503 progressPanel.add(thisprogress);
1504 ((GridLayout) progressPanel.getLayout())
1505 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1506 ++totalProgressCount;
1507 instance.validate();
1508 return thisprogress;
1511 int totalProgressCount = 0;
1513 private void removeProgressPanel(JPanel progbar)
1515 if (progressPanel != null)
1517 progressPanel.remove(progbar);
1518 GridLayout gl = (GridLayout) progressPanel.getLayout();
1519 gl.setRows(gl.getRows() - 1);
1520 if (--totalProgressCount < 1)
1522 this.getContentPane().remove(progressPanel);
1523 progressPanel = null;
1529 public void stopLoading()
1532 if (fileLoadingCount < 1)
1534 for (JPanel flp : fileLoadingPanels)
1536 removeProgressPanel(flp);
1538 fileLoadingPanels.clear();
1539 fileLoadingCount = 0;
1544 public static int getViewCount(String alignmentId)
1546 AlignViewport[] aps = getViewports(alignmentId);
1547 return (aps == null) ? 0 : aps.length;
1552 * @param alignmentId
1553 * @return all AlignmentPanels concerning the alignmentId sequence set
1555 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1558 if (Desktop.desktop == null)
1560 // no frames created and in headless mode
1561 // TODO: verify that frames are recoverable when in headless mode
1564 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1565 ArrayList aps = new ArrayList();
1566 for (int t = 0; t < frames.length; t++)
1568 if (frames[t] instanceof AlignFrame)
1570 AlignFrame af = (AlignFrame) frames[t];
1571 for (int a = 0; a < af.alignPanels.size(); a++)
1573 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1574 .elementAt(a)).av.getSequenceSetId()))
1576 aps.add(af.alignPanels.elementAt(a));
1581 if (aps.size() == 0)
1585 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1586 for (int t = 0; t < vap.length; t++)
1588 vap[t] = (AlignmentPanel) aps.get(t);
1594 * get all the viewports on an alignment.
1596 * @param sequenceSetId
1597 * unique alignment id
1598 * @return all viewports on the alignment bound to sequenceSetId
1600 public static AlignViewport[] getViewports(String sequenceSetId)
1602 Vector viewp = new Vector();
1603 if (desktop != null)
1605 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1607 for (int t = 0; t < frames.length; t++)
1609 if (frames[t] instanceof AlignFrame)
1611 AlignFrame afr = ((AlignFrame) frames[t]);
1612 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1614 if (afr.alignPanels != null)
1616 for (int a = 0; a < afr.alignPanels.size(); a++)
1618 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1619 .elementAt(a)).av.getSequenceSetId()))
1621 viewp.addElement(((AlignmentPanel) afr.alignPanels
1628 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1633 if (viewp.size() > 0)
1635 AlignViewport[] vp = new AlignViewport[viewp.size()];
1643 public void explodeViews(AlignFrame af)
1645 int size = af.alignPanels.size();
1651 for (int i = 0; i < size; i++)
1653 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1654 AlignFrame newaf = new AlignFrame(ap);
1655 if (ap.av.explodedPosition != null
1656 && !ap.av.explodedPosition.equals(af.getBounds()))
1658 newaf.setBounds(ap.av.explodedPosition);
1661 ap.av.gatherViewsHere = false;
1663 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1664 AlignFrame.DEFAULT_HEIGHT);
1667 af.alignPanels.clear();
1668 af.closeMenuItem_actionPerformed(true);
1672 public void gatherViews(AlignFrame source)
1674 source.viewport.gatherViewsHere = true;
1675 source.viewport.explodedPosition = source.getBounds();
1676 JInternalFrame[] frames = desktop.getAllFrames();
1677 String viewId = source.viewport.getSequenceSetId();
1679 for (int t = 0; t < frames.length; t++)
1681 if (frames[t] instanceof AlignFrame && frames[t] != source)
1683 AlignFrame af = (AlignFrame) frames[t];
1684 boolean gatherThis = false;
1685 for (int a = 0; a < af.alignPanels.size(); a++)
1687 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1688 if (viewId.equals(ap.av.getSequenceSetId()))
1691 ap.av.gatherViewsHere = false;
1692 ap.av.explodedPosition = af.getBounds();
1693 source.addAlignmentPanel(ap, false);
1699 af.alignPanels.clear();
1700 af.closeMenuItem_actionPerformed(true);
1707 jalview.gui.VamsasApplication v_client = null;
1709 public void vamsasImport_actionPerformed(ActionEvent e)
1711 if (v_client == null)
1713 // Load and try to start a session.
1714 JalviewFileChooser chooser = new JalviewFileChooser(
1715 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1717 chooser.setFileView(new JalviewFileView());
1718 chooser.setDialogTitle("Open a saved VAMSAS session");
1719 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1721 int value = chooser.showOpenDialog(this);
1723 if (value == JalviewFileChooser.APPROVE_OPTION)
1725 String fle = chooser.getSelectedFile().toString();
1726 if (!vamsasImport(chooser.getSelectedFile()))
1728 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1729 "Couldn't import '" + fle + "' as a new vamsas session.",
1730 "Vamsas Document Import Failed",
1731 JOptionPane.ERROR_MESSAGE);
1737 jalview.bin.Cache.log
1738 .error("Implementation error - load session from a running session is not supported.");
1743 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1746 * @return true if import was a success and a session was started.
1748 public boolean vamsasImport(URL url)
1750 // TODO: create progress bar
1751 if (v_client != null)
1754 jalview.bin.Cache.log
1755 .error("Implementation error - load session from a running session is not supported.");
1761 // copy the URL content to a temporary local file
1762 // TODO: be a bit cleverer here with nio (?!)
1763 File file = File.createTempFile("vdocfromurl", ".vdj");
1764 FileOutputStream fos = new FileOutputStream(file);
1765 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1766 byte[] buffer = new byte[2048];
1768 while ((ln = bis.read(buffer)) > -1)
1770 fos.write(buffer, 0, ln);
1774 v_client = new jalview.gui.VamsasApplication(this, file,
1775 url.toExternalForm());
1776 } catch (Exception ex)
1778 jalview.bin.Cache.log.error(
1779 "Failed to create new vamsas session from contents of URL "
1783 setupVamsasConnectedGui();
1784 v_client.initial_update(); // TODO: thread ?
1785 return v_client.inSession();
1789 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1792 * @return true if import was a success and a session was started.
1794 public boolean vamsasImport(File file)
1796 if (v_client != null)
1799 jalview.bin.Cache.log
1800 .error("Implementation error - load session from a running session is not supported.");
1804 setProgressBar("Importing VAMSAS session from " + file.getName(),
1808 v_client = new jalview.gui.VamsasApplication(this, file, null);
1809 } catch (Exception ex)
1811 setProgressBar("Importing VAMSAS session from " + file.getName(),
1813 jalview.bin.Cache.log.error(
1814 "New vamsas session from existing session file failed:", ex);
1817 setupVamsasConnectedGui();
1818 v_client.initial_update(); // TODO: thread ?
1819 setProgressBar("Importing VAMSAS session from " + file.getName(),
1821 return v_client.inSession();
1824 public boolean joinVamsasSession(String mysesid)
1826 if (v_client != null)
1829 "Trying to join a vamsas session when another is already connected.");
1831 if (mysesid == null)
1833 throw new Error("Invalid vamsas session id.");
1835 v_client = new VamsasApplication(this, mysesid);
1836 setupVamsasConnectedGui();
1837 v_client.initial_update();
1838 return (v_client.inSession());
1841 public void vamsasStart_actionPerformed(ActionEvent e)
1843 if (v_client == null)
1846 // we just start a default session for moment.
1848 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1849 * getProperty("LAST_DIRECTORY"));
1851 * chooser.setFileView(new JalviewFileView());
1852 * chooser.setDialogTitle("Load Vamsas file");
1853 * chooser.setToolTipText("Import");
1855 * int value = chooser.showOpenDialog(this);
1857 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1858 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1860 v_client = new VamsasApplication(this);
1861 setupVamsasConnectedGui();
1862 v_client.initial_update(); // TODO: thread ?
1866 // store current data in session.
1867 v_client.push_update(); // TODO: thread
1871 protected void setupVamsasConnectedGui()
1873 vamsasStart.setText("Session Update");
1874 vamsasSave.setVisible(true);
1875 vamsasStop.setVisible(true);
1876 vamsasImport.setVisible(false); // Document import to existing session is
1877 // not possible for vamsas-client-1.0.
1880 protected void setupVamsasDisconnectedGui()
1882 vamsasSave.setVisible(false);
1883 vamsasStop.setVisible(false);
1884 vamsasImport.setVisible(true);
1885 vamsasStart.setText("New Vamsas Session");
1888 public void vamsasStop_actionPerformed(ActionEvent e)
1890 if (v_client != null)
1892 v_client.end_session();
1894 setupVamsasDisconnectedGui();
1898 protected void buildVamsasStMenu()
1900 if (v_client == null)
1902 String[] sess = null;
1905 sess = VamsasApplication.getSessionList();
1906 } catch (Exception e)
1908 jalview.bin.Cache.log.warn(
1909 "Problem getting current sessions list.", e);
1914 jalview.bin.Cache.log.debug("Got current sessions list: "
1915 + sess.length + " entries.");
1916 VamsasStMenu.removeAll();
1917 for (int i = 0; i < sess.length; i++)
1919 JMenuItem sessit = new JMenuItem();
1920 sessit.setText(sess[i]);
1921 sessit.setToolTipText("Connect to session " + sess[i]);
1922 final Desktop dsktp = this;
1923 final String mysesid = sess[i];
1924 sessit.addActionListener(new ActionListener()
1927 public void actionPerformed(ActionEvent e)
1929 if (dsktp.v_client == null)
1931 Thread rthr = new Thread(new Runnable()
1936 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1937 dsktp.setupVamsasConnectedGui();
1938 dsktp.v_client.initial_update();
1946 VamsasStMenu.add(sessit);
1948 // don't show an empty menu.
1949 VamsasStMenu.setVisible(sess.length > 0);
1954 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1955 VamsasStMenu.removeAll();
1956 VamsasStMenu.setVisible(false);
1961 // Not interested in the content. Just hide ourselves.
1962 VamsasStMenu.setVisible(false);
1966 public void vamsasSave_actionPerformed(ActionEvent e)
1968 if (v_client != null)
1970 JalviewFileChooser chooser = new JalviewFileChooser(
1971 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1972 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1974 { "Vamsas Document" }, "Vamsas Document");
1976 chooser.setFileView(new JalviewFileView());
1977 chooser.setDialogTitle("Save Vamsas Document Archive");
1979 int value = chooser.showSaveDialog(this);
1981 if (value == JalviewFileChooser.APPROVE_OPTION)
1983 java.io.File choice = chooser.getSelectedFile();
1984 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1985 + choice.getName());
1986 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1987 String warnmsg = null;
1988 String warnttl = null;
1991 v_client.vclient.storeDocument(choice);
1994 warnttl = "Serious Problem saving Vamsas Document";
1995 warnmsg = ex.toString();
1996 jalview.bin.Cache.log.error("Error Whilst saving document to "
1999 } catch (Exception ex)
2001 warnttl = "Problem saving Vamsas Document.";
2002 warnmsg = ex.toString();
2003 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2007 removeProgressPanel(progpanel);
2008 if (warnmsg != null)
2010 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2012 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2018 JPanel vamUpdate = null;
2021 * hide vamsas user gui bits when a vamsas document event is being handled.
2024 * true to hide gui, false to reveal gui
2026 public void setVamsasUpdate(boolean b)
2028 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2029 + (b ? "in progress" : "finished"));
2031 if (vamUpdate != null)
2033 this.removeProgressPanel(vamUpdate);
2037 vamUpdate = this.addProgressPanel("Updating vamsas session");
2039 vamsasStart.setVisible(!b);
2040 vamsasStop.setVisible(!b);
2041 vamsasSave.setVisible(!b);
2044 public JInternalFrame[] getAllFrames()
2046 return desktop.getAllFrames();
2050 * Checks the given url to see if it gives a response indicating that the user
2051 * should be informed of a new questionnaire.
2055 public void checkForQuestionnaire(String url)
2057 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2058 // javax.swing.SwingUtilities.invokeLater(jvq);
2059 new Thread(jvq).start();
2063 * Proxy class for JDesktopPane which optionally displays the current memory
2064 * usage and highlights the desktop area with a red bar if free memory runs
2069 public class MyDesktopPane extends JDesktopPane implements Runnable
2072 boolean showMemoryUsage = false;
2076 java.text.NumberFormat df;
2078 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2081 public MyDesktopPane(boolean showMemoryUsage)
2083 showMemoryUsage(showMemoryUsage);
2086 public void showMemoryUsage(boolean showMemoryUsage)
2088 this.showMemoryUsage = showMemoryUsage;
2089 if (showMemoryUsage)
2091 Thread worker = new Thread(this);
2096 public boolean isShowMemoryUsage()
2098 return showMemoryUsage;
2103 df = java.text.NumberFormat.getNumberInstance();
2104 df.setMaximumFractionDigits(2);
2105 runtime = Runtime.getRuntime();
2107 while (showMemoryUsage)
2111 maxMemory = runtime.maxMemory() / 1048576f;
2112 allocatedMemory = runtime.totalMemory() / 1048576f;
2113 freeMemory = runtime.freeMemory() / 1048576f;
2114 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2116 percentUsage = (totalFreeMemory / maxMemory) * 100;
2118 // if (percentUsage < 20)
2120 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2122 // instance.set.setBorder(border1);
2125 // sleep after showing usage
2127 } catch (Exception ex)
2129 ex.printStackTrace();
2134 public void paintComponent(Graphics g)
2136 if (showMemoryUsage && g != null && df != null)
2138 if (percentUsage < 20)
2139 g.setColor(Color.red);
2140 FontMetrics fm = g.getFontMetrics();
2144 "Total Free Memory: " + df.format(totalFreeMemory)
2145 + "MB; Max Memory: " + df.format(maxMemory)
2146 + "MB; " + df.format(percentUsage) + "%", 10,
2147 getHeight() - fm.getHeight());
2154 * fixes stacking order after a modal dialog to ensure windows that should be
2155 * on top actually are
2157 public void relayerWindows()
2162 protected JMenuItem groovyShell;
2164 public void doGroovyCheck()
2166 if (jalview.bin.Cache.groovyJarsPresent())
2168 groovyShell = new JMenuItem();
2169 groovyShell.setText("Groovy Console...");
2170 groovyShell.addActionListener(new ActionListener()
2172 public void actionPerformed(ActionEvent e)
2174 groovyShell_actionPerformed(e);
2177 toolsMenu.add(groovyShell);
2178 groovyShell.setVisible(true);
2183 * Accessor method to quickly get all the AlignmentFrames loaded.
2185 public static AlignFrame[] getAlignframes()
2187 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2193 Vector avp = new Vector();
2197 for (int i = frames.length - 1; i > -1; i--)
2199 if (frames[i] instanceof AlignFrame)
2201 AlignFrame af = (AlignFrame) frames[i];
2205 } catch (Exception ex)
2207 ex.printStackTrace();
2209 if (avp.size() == 0)
2213 AlignFrame afs[] = new AlignFrame[avp.size()];
2214 for (int i = 0, j = avp.size(); i < j; i++)
2216 afs[i] = (AlignFrame) avp.elementAt(i);
2222 public AppJmol[] getJmols()
2224 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2230 Vector avp = new Vector();
2234 for (int i = frames.length - 1; i > -1; i--)
2236 if (frames[i] instanceof AppJmol)
2238 AppJmol af = (AppJmol) frames[i];
2242 } catch (Exception ex)
2244 ex.printStackTrace();
2246 if (avp.size() == 0)
2250 AppJmol afs[] = new AppJmol[avp.size()];
2251 for (int i = 0, j = avp.size(); i < j; i++)
2253 afs[i] = (AppJmol) avp.elementAt(i);
2260 * Add Groovy Support to Jalview
2262 public void groovyShell_actionPerformed(ActionEvent e)
2264 // use reflection to avoid creating compilation dependency.
2265 if (!jalview.bin.Cache.groovyJarsPresent())
2268 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2272 Class gcClass = Desktop.class.getClassLoader().loadClass(
2273 "groovy.ui.Console");
2274 Constructor gccons = gcClass.getConstructor(null);
2275 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2277 { String.class, Object.class });
2278 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2279 Object gc = gccons.newInstance(null);
2280 setvar.invoke(gc, new Object[]
2281 { "Jalview", this });
2282 run.invoke(gc, null);
2283 } catch (Exception ex)
2285 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2287 .showInternalMessageDialog(
2290 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2291 "Jalview Groovy Support Failed",
2292 JOptionPane.ERROR_MESSAGE);
2297 * Progress bars managed by the IProgressIndicator method.
2299 private Hashtable<Long, JPanel> progressBars;
2301 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2306 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2308 public void setProgressBar(String message, long id)
2310 if (progressBars == null)
2312 progressBars = new Hashtable<Long, JPanel>();
2313 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2316 if (progressBars.get(new Long(id)) != null)
2318 JPanel progressPanel = progressBars.remove(new Long(id));
2319 if (progressBarHandlers.contains(new Long(id)))
2321 progressBarHandlers.remove(new Long(id));
2323 removeProgressPanel(progressPanel);
2327 progressBars.put(new Long(id), addProgressPanel(message));
2334 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2335 * jalview.gui.IProgressIndicatorHandler)
2337 public void registerHandler(final long id,
2338 final IProgressIndicatorHandler handler)
2340 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2343 "call setProgressBar before registering the progress bar's handler.");
2345 progressBarHandlers.put(new Long(id), handler);
2346 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2347 if (handler.canCancel())
2349 JButton cancel = new JButton("Cancel");
2350 final IProgressIndicator us = this;
2351 cancel.addActionListener(new ActionListener()
2354 public void actionPerformed(ActionEvent e)
2356 handler.cancelActivity(id);
2359 + ((JLabel) progressPanel.getComponent(0))
2363 progressPanel.add(cancel, BorderLayout.EAST);
2369 * @return true if any progress bars are still active
2372 public boolean operationInProgress()
2374 if (progressBars != null && progressBars.size() > 0)
2382 * This will return the first AlignFrame viewing AlignViewport av. It will
2383 * break if there are more than one AlignFrames viewing a particular av. This
2386 * @return alignFrame for av
2388 public static AlignFrame getAlignFrameFor(AlignViewport av)
2390 if (desktop != null)
2392 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2393 for (int panel = 0; aps != null && panel < aps.length; panel++)
2395 if (aps[panel] != null && aps[panel].av == av)
2397 return aps[panel].alignFrame;
2404 public VamsasApplication getVamsasApplication()
2411 * flag set if jalview GUI is being operated programmatically
2413 private boolean inBatchMode = false;
2416 * check if jalview GUI is being operated programmatically
2418 * @return inBatchMode
2420 public boolean isInBatchMode()
2426 * set flag if jalview GUI is being operated programmatically
2428 * @param inBatchMode
2430 public void setInBatchMode(boolean inBatchMode)
2432 this.inBatchMode = inBatchMode;
2435 public void startServiceDiscovery()
2437 startServiceDiscovery(false);
2440 public void startServiceDiscovery(boolean blocking)
2442 boolean alive = true;
2443 Thread t0 = null, t1 = null, t2 = null;
2445 // todo: changesupport handlers need to be transferred
2446 if (discoverer == null)
2448 discoverer = new jalview.ws.jws1.Discoverer();
2449 // register PCS handler for desktop.
2450 discoverer.addPropertyChangeListener(changeSupport);
2452 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2453 // until we phase out completely
2456 (t0 = new Thread(discoverer)).start();
2461 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2463 // EnfinEnvision web service menu entries are rebuild every time the
2464 // menu is shown, so no changeSupport events are needed.
2465 jalview.ws.EnfinEnvision2OneWay.getInstance();
2466 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2469 } catch (Exception e)
2472 .info("Exception when trying to launch Envision2 workflow discovery.",
2474 Cache.log.info(e.getStackTrace());
2476 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2478 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2480 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2482 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2488 // TODO: do rest service discovery
2497 } catch (Exception e)
2500 alive = (t1 != null && t1.isAlive())
2501 || (t2 != null && t2.isAlive())
2502 || (t3 != null && t3.isAlive())
2503 || (t0 != null && t0.isAlive());
2509 * called to check if the service discovery process completed successfully.
2513 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2515 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2517 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2518 .getErrorMessages();
2521 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2523 if (serviceChangedDialog == null)
2525 // only run if we aren't already displaying one of these.
2526 addDialogThread(serviceChangedDialog = new Runnable()
2532 * JalviewDialog jd =new JalviewDialog() {
2534 * @Override protected void cancelPressed() { // TODO
2535 * Auto-generated method stub
2537 * }@Override protected void okPressed() { // TODO
2538 * Auto-generated method stub
2540 * }@Override protected void raiseClosed() { // TODO
2541 * Auto-generated method stub
2543 * } }; jd.initDialogFrame(new
2544 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2545 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2546 * + " or mis-configured HTTP proxy settings.<br/>" +
2547 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2549 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2550 * ), true, true, "Web Service Configuration Problem", 450,
2553 * jd.waitForInput();
2559 "<html><table width=\"450\"><tr><td>"
2561 + "</td></tr></table>"
2562 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2563 + " or mis-configured HTTP proxy settings.</p>"
2564 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2565 + " Tools->Preferences dialog box to change them.</p></html>"),
2566 "Web Service Configuration Problem",
2567 JOptionPane.DEFAULT_OPTION,
2568 JOptionPane.ERROR_MESSAGE);
2569 serviceChangedDialog = null;
2578 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2585 private Runnable serviceChangedDialog = null;
2588 * start a thread to open a URL in the configured browser. Pops up a warning
2589 * dialog to the user if there is an exception when calling out to the browser
2594 public static void showUrl(final String url)
2596 showUrl(url, Desktop.instance);
2600 * Like showUrl but allows progress handler to be specified
2604 * (null) or object implementing IProgressIndicator
2606 public static void showUrl(final String url,
2607 final IProgressIndicator progress)
2609 new Thread(new Runnable()
2615 if (progress != null)
2617 progress.setProgressBar("Opening " + url, this.hashCode());
2619 jalview.util.BrowserLauncher.openURL(url);
2620 } catch (Exception ex)
2623 .showInternalMessageDialog(
2625 "Unixers: Couldn't find default web browser."
2626 + "\nAdd the full path to your browser in Preferences.",
2627 "Web browser not found",
2628 JOptionPane.WARNING_MESSAGE);
2630 ex.printStackTrace();
2632 if (progress != null)
2634 progress.setProgressBar(null, this.hashCode());
2640 public static WsParamSetManager wsparamManager = null;
2642 public static ParamManager getUserParameterStore()
2644 if (wsparamManager == null)
2646 wsparamManager = new WsParamSetManager();
2648 return wsparamManager;
2652 * static hyperlink handler proxy method for use by Jalview's internal windows
2656 public static void hyperlinkUpdate(HyperlinkEvent e)
2658 if (e.getEventType() == EventType.ACTIVATED)
2663 url = e.getURL().toString();
2664 Desktop.showUrl(url);
2665 } catch (Exception x)
2669 if (Cache.log != null)
2671 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2675 System.err.println("Couldn't handle string " + url
2679 // ignore any exceptions due to dud links.
2686 * single thread that handles display of dialogs to user.
2688 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2691 * flag indicating if dialogExecutor should try to acquire a permit
2693 private volatile boolean dialogPause = true;
2698 private java.util.concurrent.Semaphore block = new Semaphore(0);
2701 * add another dialog thread to the queue
2705 public void addDialogThread(final Runnable prompter)
2707 dialogExecutor.submit(new Runnable()
2716 } catch (InterruptedException x)
2721 if (instance == null)
2727 SwingUtilities.invokeAndWait(prompter);
2728 } catch (Exception q)
2730 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2736 public void startDialogQueue()
2738 // set the flag so we don't pause waiting for another permit and semaphore
2739 // the current task to begin
2740 dialogPause = false;