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(JFrame.EXIT_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 (instance == null || (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();
1060 private void storeLastKnownDimensions(String string, Rectangle jc)
1062 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1063 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1064 + " height:" + jc.height);
1066 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1067 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1068 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1069 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1078 public void aboutMenuItem_actionPerformed(ActionEvent e)
1080 // StringBuffer message = getAboutMessage(false);
1081 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1083 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1084 new Thread(new Runnable()
1088 new SplashScreen(true);
1093 public StringBuffer getAboutMessage(boolean shortv)
1095 StringBuffer message = new StringBuffer();
1096 message.append("<html>");
1099 message.append("<h1><strong>Version: "
1100 + jalview.bin.Cache.getProperty("VERSION")
1101 + "</strong></h1><br>");
1102 message.append("<strong>Last Updated: <em>"
1103 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1104 + "</em></strong>");
1110 message.append("<strong>Version "
1111 + jalview.bin.Cache.getProperty("VERSION")
1112 + "; last updated: "
1113 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1116 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1119 message.append("<br>...Checking latest version...</br>");
1121 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1122 .equals(jalview.bin.Cache.getProperty("VERSION")))
1124 boolean red = false;
1125 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1126 .indexOf("automated build") == -1)
1129 // Displayed when code version and jnlp version do not match and code
1130 // version is not a development build
1131 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1134 message.append("<br>!! Version "
1135 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1137 + " is available for download from "
1138 + jalview.bin.Cache.getDefault("www.jalview.org",
1139 "http://www.jalview.org") + " !!");
1142 message.append("</div>");
1145 message.append("<br>Authors: "
1149 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1150 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1151 + "<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"
1152 + "<br>If you use Jalview, please cite:"
1153 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1154 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1155 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1166 public void documentationMenuItem_actionPerformed(ActionEvent e)
1170 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1171 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1172 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1174 javax.help.HelpBroker hb = hs.createHelpBroker();
1175 hb.setCurrentID("home");
1176 hb.setDisplayed(true);
1177 } catch (Exception ex)
1182 public void closeAll_actionPerformed(ActionEvent e)
1184 JInternalFrame[] frames = desktop.getAllFrames();
1185 for (int i = 0; i < frames.length; i++)
1189 frames[i].setClosed(true);
1190 } catch (java.beans.PropertyVetoException ex)
1194 System.out.println("ALL CLOSED");
1195 if (v_client != null)
1197 // TODO clear binding to vamsas document objects on close_all
1202 public void raiseRelated_actionPerformed(ActionEvent e)
1204 reorderAssociatedWindows(false, false);
1207 public void minimizeAssociated_actionPerformed(ActionEvent e)
1209 reorderAssociatedWindows(true, false);
1212 void closeAssociatedWindows()
1214 reorderAssociatedWindows(false, true);
1220 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1223 protected void garbageCollect_actionPerformed(ActionEvent e)
1225 // We simply collect the garbage
1226 jalview.bin.Cache.log.debug("Collecting garbage...");
1228 jalview.bin.Cache.log.debug("Finished garbage collection.");
1235 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1238 protected void showMemusage_actionPerformed(ActionEvent e)
1240 desktop.showMemoryUsage(showMemusage.isSelected());
1247 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1250 protected void showConsole_actionPerformed(ActionEvent e)
1252 showConsole(showConsole.isSelected());
1255 Console jconsole = null;
1258 * control whether the java console is visible or not
1262 void showConsole(boolean selected)
1264 showConsole.setSelected(selected);
1265 // TODO: decide if we should update properties file
1266 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1268 jconsole.setVisible(selected);
1271 void reorderAssociatedWindows(boolean minimize, boolean close)
1273 JInternalFrame[] frames = desktop.getAllFrames();
1274 if (frames == null || frames.length < 1)
1279 AlignViewport source = null, target = null;
1280 if (frames[0] instanceof AlignFrame)
1282 source = ((AlignFrame) frames[0]).getCurrentView();
1284 else if (frames[0] instanceof TreePanel)
1286 source = ((TreePanel) frames[0]).getViewPort();
1288 else if (frames[0] instanceof PCAPanel)
1290 source = ((PCAPanel) frames[0]).av;
1292 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1294 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1299 for (int i = 0; i < frames.length; i++)
1302 if (frames[i] == null)
1306 if (frames[i] instanceof AlignFrame)
1308 target = ((AlignFrame) frames[i]).getCurrentView();
1310 else if (frames[i] instanceof TreePanel)
1312 target = ((TreePanel) frames[i]).getViewPort();
1314 else if (frames[i] instanceof PCAPanel)
1316 target = ((PCAPanel) frames[i]).av;
1318 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1320 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1323 if (source == target)
1329 frames[i].setClosed(true);
1333 frames[i].setIcon(minimize);
1336 frames[i].toFront();
1340 } catch (java.beans.PropertyVetoException ex)
1354 protected void preferences_actionPerformed(ActionEvent e)
1365 public void saveState_actionPerformed(ActionEvent e)
1367 JalviewFileChooser chooser = new JalviewFileChooser(
1368 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1369 { "jar" }, new String[]
1370 { "Jalview Project" }, "Jalview Project");
1372 chooser.setFileView(new JalviewFileView());
1373 chooser.setDialogTitle("Save State");
1375 int value = chooser.showSaveDialog(this);
1377 if (value == JalviewFileChooser.APPROVE_OPTION)
1379 final Desktop me = this;
1380 final java.io.File choice = chooser.getSelectedFile();
1381 new Thread(new Runnable()
1386 setProgressBar("Saving jalview project " + choice.getName(),
1388 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1389 choice.getParent());
1390 // TODO catch and handle errors for savestate
1391 // TODO prevent user from messing with the Desktop whilst we're saving
1394 new Jalview2XML().SaveState(choice);
1395 } catch (OutOfMemoryError oom)
1397 new OOMWarning("Whilst saving current state to "
1398 + choice.getName(), oom);
1399 } catch (Exception ex)
1402 "Problems whilst trying to save to " + choice.getName(),
1404 JOptionPane.showMessageDialog(
1406 "Error whilst saving current state to "
1407 + choice.getName(), "Couldn't save project",
1408 JOptionPane.WARNING_MESSAGE);
1410 setProgressBar(null, choice.hashCode());
1422 public void loadState_actionPerformed(ActionEvent e)
1424 JalviewFileChooser chooser = new JalviewFileChooser(
1425 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1426 { "jar" }, new String[]
1427 { "Jalview Project" }, "Jalview Project");
1428 chooser.setFileView(new JalviewFileView());
1429 chooser.setDialogTitle("Restore state");
1431 int value = chooser.showOpenDialog(this);
1433 if (value == JalviewFileChooser.APPROVE_OPTION)
1435 final String choice = chooser.getSelectedFile().getAbsolutePath();
1436 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1437 .getSelectedFile().getParent());
1438 new Thread(new Runnable()
1442 setProgressBar("loading jalview project " + choice,
1446 new Jalview2XML().LoadJalviewAlign(choice);
1447 } catch (OutOfMemoryError oom)
1449 new OOMWarning("Whilst loading project from " + choice, oom);
1450 } catch (Exception ex)
1452 Cache.log.error("Problems whilst loading project from "
1454 JOptionPane.showMessageDialog(Desktop.desktop,
1455 "Error whilst loading project from " + choice,
1456 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1458 setProgressBar(null, choice.hashCode());
1464 public void inputSequence_actionPerformed(ActionEvent e)
1466 new SequenceFetcher(this);
1469 JPanel progressPanel;
1471 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1473 public void startLoading(final String fileName)
1475 if (fileLoadingCount == 0)
1477 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1483 private JPanel addProgressPanel(String string)
1485 if (progressPanel == null)
1487 progressPanel = new JPanel(new GridLayout(1, 1));
1488 totalProgressCount = 0;
1489 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1491 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1492 JProgressBar progressBar = new JProgressBar();
1493 progressBar.setIndeterminate(true);
1495 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1497 thisprogress.add(progressBar, BorderLayout.CENTER);
1498 progressPanel.add(thisprogress);
1499 ((GridLayout) progressPanel.getLayout())
1500 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1501 ++totalProgressCount;
1502 instance.validate();
1503 return thisprogress;
1506 int totalProgressCount = 0;
1508 private void removeProgressPanel(JPanel progbar)
1510 if (progressPanel != null)
1512 progressPanel.remove(progbar);
1513 GridLayout gl = (GridLayout) progressPanel.getLayout();
1514 gl.setRows(gl.getRows() - 1);
1515 if (--totalProgressCount < 1)
1517 this.getContentPane().remove(progressPanel);
1518 progressPanel = null;
1524 public void stopLoading()
1527 if (fileLoadingCount < 1)
1529 for (JPanel flp : fileLoadingPanels)
1531 removeProgressPanel(flp);
1533 fileLoadingPanels.clear();
1534 fileLoadingCount = 0;
1539 public static int getViewCount(String alignmentId)
1541 AlignViewport[] aps = getViewports(alignmentId);
1542 return (aps == null) ? 0 : aps.length;
1547 * @param alignmentId
1548 * @return all AlignmentPanels concerning the alignmentId sequence set
1550 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1553 if (Desktop.desktop == null)
1555 // no frames created and in headless mode
1556 // TODO: verify that frames are recoverable when in headless mode
1559 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1560 ArrayList aps = new ArrayList();
1561 for (int t = 0; t < frames.length; t++)
1563 if (frames[t] instanceof AlignFrame)
1565 AlignFrame af = (AlignFrame) frames[t];
1566 for (int a = 0; a < af.alignPanels.size(); a++)
1568 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1569 .elementAt(a)).av.getSequenceSetId()))
1571 aps.add(af.alignPanels.elementAt(a));
1576 if (aps.size() == 0)
1580 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1581 for (int t = 0; t < vap.length; t++)
1583 vap[t] = (AlignmentPanel) aps.get(t);
1589 * get all the viewports on an alignment.
1591 * @param sequenceSetId
1592 * unique alignment id
1593 * @return all viewports on the alignment bound to sequenceSetId
1595 public static AlignViewport[] getViewports(String sequenceSetId)
1597 Vector viewp = new Vector();
1598 if (desktop != null)
1600 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1602 for (int t = 0; t < frames.length; t++)
1604 if (frames[t] instanceof AlignFrame)
1606 AlignFrame afr = ((AlignFrame) frames[t]);
1607 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1609 if (afr.alignPanels != null)
1611 for (int a = 0; a < afr.alignPanels.size(); a++)
1613 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1614 .elementAt(a)).av.getSequenceSetId()))
1616 viewp.addElement(((AlignmentPanel) afr.alignPanels
1623 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1628 if (viewp.size() > 0)
1630 AlignViewport[] vp = new AlignViewport[viewp.size()];
1638 public void explodeViews(AlignFrame af)
1640 int size = af.alignPanels.size();
1646 for (int i = 0; i < size; i++)
1648 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1649 AlignFrame newaf = new AlignFrame(ap);
1650 if (ap.av.explodedPosition != null
1651 && !ap.av.explodedPosition.equals(af.getBounds()))
1653 newaf.setBounds(ap.av.explodedPosition);
1656 ap.av.gatherViewsHere = false;
1658 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1659 AlignFrame.DEFAULT_HEIGHT);
1662 af.alignPanels.clear();
1663 af.closeMenuItem_actionPerformed(true);
1667 public void gatherViews(AlignFrame source)
1669 source.viewport.gatherViewsHere = true;
1670 source.viewport.explodedPosition = source.getBounds();
1671 JInternalFrame[] frames = desktop.getAllFrames();
1672 String viewId = source.viewport.getSequenceSetId();
1674 for (int t = 0; t < frames.length; t++)
1676 if (frames[t] instanceof AlignFrame && frames[t] != source)
1678 AlignFrame af = (AlignFrame) frames[t];
1679 boolean gatherThis = false;
1680 for (int a = 0; a < af.alignPanels.size(); a++)
1682 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1683 if (viewId.equals(ap.av.getSequenceSetId()))
1686 ap.av.gatherViewsHere = false;
1687 ap.av.explodedPosition = af.getBounds();
1688 source.addAlignmentPanel(ap, false);
1694 af.alignPanels.clear();
1695 af.closeMenuItem_actionPerformed(true);
1702 jalview.gui.VamsasApplication v_client = null;
1704 public void vamsasImport_actionPerformed(ActionEvent e)
1706 if (v_client == null)
1708 // Load and try to start a session.
1709 JalviewFileChooser chooser = new JalviewFileChooser(
1710 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1712 chooser.setFileView(new JalviewFileView());
1713 chooser.setDialogTitle("Open a saved VAMSAS session");
1714 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1716 int value = chooser.showOpenDialog(this);
1718 if (value == JalviewFileChooser.APPROVE_OPTION)
1720 String fle = chooser.getSelectedFile().toString();
1721 if (!vamsasImport(chooser.getSelectedFile()))
1723 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1724 "Couldn't import '" + fle + "' as a new vamsas session.",
1725 "Vamsas Document Import Failed",
1726 JOptionPane.ERROR_MESSAGE);
1732 jalview.bin.Cache.log
1733 .error("Implementation error - load session from a running session is not supported.");
1738 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1741 * @return true if import was a success and a session was started.
1743 public boolean vamsasImport(URL url)
1745 // TODO: create progress bar
1746 if (v_client != null)
1749 jalview.bin.Cache.log
1750 .error("Implementation error - load session from a running session is not supported.");
1756 // copy the URL content to a temporary local file
1757 // TODO: be a bit cleverer here with nio (?!)
1758 File file = File.createTempFile("vdocfromurl", ".vdj");
1759 FileOutputStream fos = new FileOutputStream(file);
1760 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1761 byte[] buffer = new byte[2048];
1763 while ((ln = bis.read(buffer)) > -1)
1765 fos.write(buffer, 0, ln);
1769 v_client = new jalview.gui.VamsasApplication(this, file,
1770 url.toExternalForm());
1771 } catch (Exception ex)
1773 jalview.bin.Cache.log.error(
1774 "Failed to create new vamsas session from contents of URL "
1778 setupVamsasConnectedGui();
1779 v_client.initial_update(); // TODO: thread ?
1780 return v_client.inSession();
1784 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1787 * @return true if import was a success and a session was started.
1789 public boolean vamsasImport(File file)
1791 if (v_client != null)
1794 jalview.bin.Cache.log
1795 .error("Implementation error - load session from a running session is not supported.");
1799 setProgressBar("Importing VAMSAS session from " + file.getName(),
1803 v_client = new jalview.gui.VamsasApplication(this, file, null);
1804 } catch (Exception ex)
1806 setProgressBar("Importing VAMSAS session from " + file.getName(),
1808 jalview.bin.Cache.log.error(
1809 "New vamsas session from existing session file failed:", ex);
1812 setupVamsasConnectedGui();
1813 v_client.initial_update(); // TODO: thread ?
1814 setProgressBar("Importing VAMSAS session from " + file.getName(),
1816 return v_client.inSession();
1819 public boolean joinVamsasSession(String mysesid)
1821 if (v_client != null)
1824 "Trying to join a vamsas session when another is already connected.");
1826 if (mysesid == null)
1828 throw new Error("Invalid vamsas session id.");
1830 v_client = new VamsasApplication(this, mysesid);
1831 setupVamsasConnectedGui();
1832 v_client.initial_update();
1833 return (v_client.inSession());
1836 public void vamsasStart_actionPerformed(ActionEvent e)
1838 if (v_client == null)
1841 // we just start a default session for moment.
1843 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1844 * getProperty("LAST_DIRECTORY"));
1846 * chooser.setFileView(new JalviewFileView());
1847 * chooser.setDialogTitle("Load Vamsas file");
1848 * chooser.setToolTipText("Import");
1850 * int value = chooser.showOpenDialog(this);
1852 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1853 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1855 v_client = new VamsasApplication(this);
1856 setupVamsasConnectedGui();
1857 v_client.initial_update(); // TODO: thread ?
1861 // store current data in session.
1862 v_client.push_update(); // TODO: thread
1866 protected void setupVamsasConnectedGui()
1868 vamsasStart.setText("Session Update");
1869 vamsasSave.setVisible(true);
1870 vamsasStop.setVisible(true);
1871 vamsasImport.setVisible(false); // Document import to existing session is
1872 // not possible for vamsas-client-1.0.
1875 protected void setupVamsasDisconnectedGui()
1877 vamsasSave.setVisible(false);
1878 vamsasStop.setVisible(false);
1879 vamsasImport.setVisible(true);
1880 vamsasStart.setText("New Vamsas Session");
1883 public void vamsasStop_actionPerformed(ActionEvent e)
1885 if (v_client != null)
1887 v_client.end_session();
1889 setupVamsasDisconnectedGui();
1893 protected void buildVamsasStMenu()
1895 if (v_client == null)
1897 String[] sess = null;
1900 sess = VamsasApplication.getSessionList();
1901 } catch (Exception e)
1903 jalview.bin.Cache.log.warn(
1904 "Problem getting current sessions list.", e);
1909 jalview.bin.Cache.log.debug("Got current sessions list: "
1910 + sess.length + " entries.");
1911 VamsasStMenu.removeAll();
1912 for (int i = 0; i < sess.length; i++)
1914 JMenuItem sessit = new JMenuItem();
1915 sessit.setText(sess[i]);
1916 sessit.setToolTipText("Connect to session " + sess[i]);
1917 final Desktop dsktp = this;
1918 final String mysesid = sess[i];
1919 sessit.addActionListener(new ActionListener()
1922 public void actionPerformed(ActionEvent e)
1924 if (dsktp.v_client == null)
1926 Thread rthr = new Thread(new Runnable()
1931 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1932 dsktp.setupVamsasConnectedGui();
1933 dsktp.v_client.initial_update();
1941 VamsasStMenu.add(sessit);
1943 // don't show an empty menu.
1944 VamsasStMenu.setVisible(sess.length > 0);
1949 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1950 VamsasStMenu.removeAll();
1951 VamsasStMenu.setVisible(false);
1956 // Not interested in the content. Just hide ourselves.
1957 VamsasStMenu.setVisible(false);
1961 public void vamsasSave_actionPerformed(ActionEvent e)
1963 if (v_client != null)
1965 JalviewFileChooser chooser = new JalviewFileChooser(
1966 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1967 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1969 { "Vamsas Document" }, "Vamsas Document");
1971 chooser.setFileView(new JalviewFileView());
1972 chooser.setDialogTitle("Save Vamsas Document Archive");
1974 int value = chooser.showSaveDialog(this);
1976 if (value == JalviewFileChooser.APPROVE_OPTION)
1978 java.io.File choice = chooser.getSelectedFile();
1979 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1980 + choice.getName());
1981 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1982 String warnmsg = null;
1983 String warnttl = null;
1986 v_client.vclient.storeDocument(choice);
1989 warnttl = "Serious Problem saving Vamsas Document";
1990 warnmsg = ex.toString();
1991 jalview.bin.Cache.log.error("Error Whilst saving document to "
1994 } catch (Exception ex)
1996 warnttl = "Problem saving Vamsas Document.";
1997 warnmsg = ex.toString();
1998 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2002 removeProgressPanel(progpanel);
2003 if (warnmsg != null)
2005 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2007 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2013 JPanel vamUpdate = null;
2016 * hide vamsas user gui bits when a vamsas document event is being handled.
2019 * true to hide gui, false to reveal gui
2021 public void setVamsasUpdate(boolean b)
2023 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2024 + (b ? "in progress" : "finished"));
2026 if (vamUpdate != null)
2028 this.removeProgressPanel(vamUpdate);
2032 vamUpdate = this.addProgressPanel("Updating vamsas session");
2034 vamsasStart.setVisible(!b);
2035 vamsasStop.setVisible(!b);
2036 vamsasSave.setVisible(!b);
2039 public JInternalFrame[] getAllFrames()
2041 return desktop.getAllFrames();
2045 * Checks the given url to see if it gives a response indicating that the user
2046 * should be informed of a new questionnaire.
2050 public void checkForQuestionnaire(String url)
2052 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2053 // javax.swing.SwingUtilities.invokeLater(jvq);
2054 new Thread(jvq).start();
2058 * Proxy class for JDesktopPane which optionally displays the current memory
2059 * usage and highlights the desktop area with a red bar if free memory runs
2064 public class MyDesktopPane extends JDesktopPane implements Runnable
2067 boolean showMemoryUsage = false;
2071 java.text.NumberFormat df;
2073 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2076 public MyDesktopPane(boolean showMemoryUsage)
2078 showMemoryUsage(showMemoryUsage);
2081 public void showMemoryUsage(boolean showMemoryUsage)
2083 this.showMemoryUsage = showMemoryUsage;
2084 if (showMemoryUsage)
2086 Thread worker = new Thread(this);
2091 public boolean isShowMemoryUsage()
2093 return showMemoryUsage;
2098 df = java.text.NumberFormat.getNumberInstance();
2099 df.setMaximumFractionDigits(2);
2100 runtime = Runtime.getRuntime();
2102 while (showMemoryUsage)
2106 maxMemory = runtime.maxMemory() / 1048576f;
2107 allocatedMemory = runtime.totalMemory() / 1048576f;
2108 freeMemory = runtime.freeMemory() / 1048576f;
2109 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2111 percentUsage = (totalFreeMemory / maxMemory) * 100;
2113 // if (percentUsage < 20)
2115 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2117 // instance.set.setBorder(border1);
2120 // sleep after showing usage
2122 } catch (Exception ex)
2124 ex.printStackTrace();
2129 public void paintComponent(Graphics g)
2131 if (showMemoryUsage && g != null && df != null)
2133 if (percentUsage < 20)
2134 g.setColor(Color.red);
2135 FontMetrics fm = g.getFontMetrics();
2139 "Total Free Memory: " + df.format(totalFreeMemory)
2140 + "MB; Max Memory: " + df.format(maxMemory)
2141 + "MB; " + df.format(percentUsage) + "%", 10,
2142 getHeight() - fm.getHeight());
2149 * fixes stacking order after a modal dialog to ensure windows that should be
2150 * on top actually are
2152 public void relayerWindows()
2157 protected JMenuItem groovyShell;
2159 public void doGroovyCheck()
2161 if (jalview.bin.Cache.groovyJarsPresent())
2163 groovyShell = new JMenuItem();
2164 groovyShell.setText("Groovy Console...");
2165 groovyShell.addActionListener(new ActionListener()
2167 public void actionPerformed(ActionEvent e)
2169 groovyShell_actionPerformed(e);
2172 toolsMenu.add(groovyShell);
2173 groovyShell.setVisible(true);
2178 * Accessor method to quickly get all the AlignmentFrames loaded.
2180 public static AlignFrame[] getAlignframes()
2182 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2188 Vector avp = new Vector();
2192 for (int i = frames.length - 1; i > -1; i--)
2194 if (frames[i] instanceof AlignFrame)
2196 AlignFrame af = (AlignFrame) frames[i];
2200 } catch (Exception ex)
2202 ex.printStackTrace();
2204 if (avp.size() == 0)
2208 AlignFrame afs[] = new AlignFrame[avp.size()];
2209 for (int i = 0, j = avp.size(); i < j; i++)
2211 afs[i] = (AlignFrame) avp.elementAt(i);
2217 public AppJmol[] getJmols()
2219 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2225 Vector avp = new Vector();
2229 for (int i = frames.length - 1; i > -1; i--)
2231 if (frames[i] instanceof AppJmol)
2233 AppJmol af = (AppJmol) frames[i];
2237 } catch (Exception ex)
2239 ex.printStackTrace();
2241 if (avp.size() == 0)
2245 AppJmol afs[] = new AppJmol[avp.size()];
2246 for (int i = 0, j = avp.size(); i < j; i++)
2248 afs[i] = (AppJmol) avp.elementAt(i);
2255 * Add Groovy Support to Jalview
2257 public void groovyShell_actionPerformed(ActionEvent e)
2259 // use reflection to avoid creating compilation dependency.
2260 if (!jalview.bin.Cache.groovyJarsPresent())
2263 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2267 Class gcClass = Desktop.class.getClassLoader().loadClass(
2268 "groovy.ui.Console");
2269 Constructor gccons = gcClass.getConstructor(null);
2270 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2272 { String.class, Object.class });
2273 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2274 Object gc = gccons.newInstance(null);
2275 setvar.invoke(gc, new Object[]
2276 { "Jalview", this });
2277 run.invoke(gc, null);
2278 } catch (Exception ex)
2280 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2282 .showInternalMessageDialog(
2285 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2286 "Jalview Groovy Support Failed",
2287 JOptionPane.ERROR_MESSAGE);
2292 * Progress bars managed by the IProgressIndicator method.
2294 private Hashtable<Long, JPanel> progressBars;
2296 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2301 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2303 public void setProgressBar(String message, long id)
2305 if (progressBars == null)
2307 progressBars = new Hashtable<Long, JPanel>();
2308 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2311 if (progressBars.get(new Long(id)) != null)
2313 JPanel progressPanel = progressBars.remove(new Long(id));
2314 if (progressBarHandlers.contains(new Long(id)))
2316 progressBarHandlers.remove(new Long(id));
2318 removeProgressPanel(progressPanel);
2322 progressBars.put(new Long(id), addProgressPanel(message));
2329 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2330 * jalview.gui.IProgressIndicatorHandler)
2332 public void registerHandler(final long id,
2333 final IProgressIndicatorHandler handler)
2335 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2338 "call setProgressBar before registering the progress bar's handler.");
2340 progressBarHandlers.put(new Long(id), handler);
2341 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2342 if (handler.canCancel())
2344 JButton cancel = new JButton("Cancel");
2345 final IProgressIndicator us = this;
2346 cancel.addActionListener(new ActionListener()
2349 public void actionPerformed(ActionEvent e)
2351 handler.cancelActivity(id);
2354 + ((JLabel) progressPanel.getComponent(0))
2358 progressPanel.add(cancel, BorderLayout.EAST);
2364 * @return true if any progress bars are still active
2367 public boolean operationInProgress()
2369 if (progressBars != null && progressBars.size() > 0)
2377 * This will return the first AlignFrame viewing AlignViewport av. It will
2378 * break if there are more than one AlignFrames viewing a particular av. This
2381 * @return alignFrame for av
2383 public static AlignFrame getAlignFrameFor(AlignViewport av)
2385 if (desktop != null)
2387 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2388 for (int panel = 0; aps != null && panel < aps.length; panel++)
2390 if (aps[panel] != null && aps[panel].av == av)
2392 return aps[panel].alignFrame;
2399 public VamsasApplication getVamsasApplication()
2406 * flag set if jalview GUI is being operated programmatically
2408 private boolean inBatchMode = false;
2411 * check if jalview GUI is being operated programmatically
2413 * @return inBatchMode
2415 public boolean isInBatchMode()
2421 * set flag if jalview GUI is being operated programmatically
2423 * @param inBatchMode
2425 public void setInBatchMode(boolean inBatchMode)
2427 this.inBatchMode = inBatchMode;
2430 public void startServiceDiscovery()
2432 startServiceDiscovery(false);
2435 public void startServiceDiscovery(boolean blocking)
2437 boolean alive = true;
2438 Thread t0 = null, t1 = null, t2 = null;
2439 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2442 // todo: changesupport handlers need to be transferred
2443 if (discoverer == null)
2445 discoverer = new jalview.ws.jws1.Discoverer();
2446 // register PCS handler for desktop.
2447 discoverer.addPropertyChangeListener(changeSupport);
2449 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2450 // until we phase out completely
2451 (t0 = new Thread(discoverer)).start();
2456 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2458 // EnfinEnvision web service menu entries are rebuild every time the
2459 // menu is shown, so no changeSupport events are needed.
2460 jalview.ws.EnfinEnvision2OneWay.getInstance();
2461 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2464 } catch (Exception e)
2467 .info("Exception when trying to launch Envision2 workflow discovery.",
2469 Cache.log.info(e.getStackTrace());
2471 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2473 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2475 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2477 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2483 // TODO: do rest service discovery
2492 } catch (Exception e)
2495 alive = (t1 != null && t1.isAlive())
2496 || (t2 != null && t2.isAlive())
2497 || (t3 != null && t3.isAlive())
2498 || (t0 != null && t0.isAlive());
2504 * called to check if the service discovery process completed successfully.
2508 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2510 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2512 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2513 .getErrorMessages();
2516 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2518 if (serviceChangedDialog == null)
2520 // only run if we aren't already displaying one of these.
2521 addDialogThread(serviceChangedDialog = new Runnable()
2527 * JalviewDialog jd =new JalviewDialog() {
2529 * @Override protected void cancelPressed() { // TODO
2530 * Auto-generated method stub
2532 * }@Override protected void okPressed() { // TODO
2533 * Auto-generated method stub
2535 * }@Override protected void raiseClosed() { // TODO
2536 * Auto-generated method stub
2538 * } }; jd.initDialogFrame(new
2539 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2540 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2541 * + " or mis-configured HTTP proxy settings.<br/>" +
2542 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2544 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2545 * ), true, true, "Web Service Configuration Problem", 450,
2548 * jd.waitForInput();
2554 "<html><table width=\"450\"><tr><td>"
2556 + "</td></tr></table>"
2557 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2558 + " or mis-configured HTTP proxy settings.</p>"
2559 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2560 + " Tools->Preferences dialog box to change them.</p></html>"),
2561 "Web Service Configuration Problem",
2562 JOptionPane.DEFAULT_OPTION,
2563 JOptionPane.ERROR_MESSAGE);
2564 serviceChangedDialog = null;
2573 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2580 private Runnable serviceChangedDialog = null;
2583 * start a thread to open a URL in the configured browser. Pops up a warning
2584 * dialog to the user if there is an exception when calling out to the browser
2589 public static void showUrl(final String url)
2591 showUrl(url, Desktop.instance);
2595 * Like showUrl but allows progress handler to be specified
2599 * (null) or object implementing IProgressIndicator
2601 public static void showUrl(final String url,
2602 final IProgressIndicator progress)
2604 new Thread(new Runnable()
2610 if (progress != null)
2612 progress.setProgressBar("Opening " + url, this.hashCode());
2614 jalview.util.BrowserLauncher.openURL(url);
2615 } catch (Exception ex)
2618 .showInternalMessageDialog(
2620 "Unixers: Couldn't find default web browser."
2621 + "\nAdd the full path to your browser in Preferences.",
2622 "Web browser not found",
2623 JOptionPane.WARNING_MESSAGE);
2625 ex.printStackTrace();
2627 if (progress != null)
2629 progress.setProgressBar(null, this.hashCode());
2635 public static WsParamSetManager wsparamManager = null;
2637 public static ParamManager getUserParameterStore()
2639 if (wsparamManager == null)
2641 wsparamManager = new WsParamSetManager();
2643 return wsparamManager;
2647 * static hyperlink handler proxy method for use by Jalview's internal windows
2651 public static void hyperlinkUpdate(HyperlinkEvent e)
2653 if (e.getEventType() == EventType.ACTIVATED)
2658 url = e.getURL().toString();
2659 Desktop.showUrl(url);
2660 } catch (Exception x)
2664 if (Cache.log != null)
2666 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2670 System.err.println("Couldn't handle string " + url
2674 // ignore any exceptions due to dud links.
2681 * single thread that handles display of dialogs to user.
2683 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2686 * flag indicating if dialogExecutor should try to acquire a permit
2688 private volatile boolean dialogPause = true;
2693 private java.util.concurrent.Semaphore block = new Semaphore(0);
2696 * add another dialog thread to the queue
2700 public void addDialogThread(final Runnable prompter)
2702 dialogExecutor.submit(new Runnable()
2711 } catch (InterruptedException x)
2716 if (instance == null)
2722 SwingUtilities.invokeAndWait(prompter);
2723 } catch (Exception q)
2725 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2731 public void startDialogQueue()
2733 // set the flag so we don't pause waiting for another permit and semaphore
2734 // the current task to begin
2735 dialogPause = false;