2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
21 import jalview.io.FileLoader;
22 import jalview.io.FormatAdapter;
23 import jalview.io.IdentifyFile;
24 import jalview.io.JalviewFileChooser;
25 import jalview.io.JalviewFileView;
26 import jalview.ws.params.ParamManager;
28 import java.awt.BorderLayout;
29 import java.awt.Color;
30 import java.awt.Dimension;
31 import java.awt.FontMetrics;
32 import java.awt.Graphics;
33 import java.awt.GridLayout;
34 import java.awt.Point;
35 import java.awt.Rectangle;
36 import java.awt.Toolkit;
37 import java.awt.datatransfer.Clipboard;
38 import java.awt.datatransfer.ClipboardOwner;
39 import java.awt.datatransfer.DataFlavor;
40 import java.awt.datatransfer.Transferable;
41 import java.awt.dnd.DnDConstants;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetEvent;
45 import java.awt.dnd.DropTargetListener;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.awt.event.MouseAdapter;
51 import java.awt.event.MouseEvent;
52 import java.awt.event.MouseListener;
53 import java.awt.event.WindowAdapter;
54 import java.awt.event.WindowEvent;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.beans.PropertyVetoException;
58 import java.io.BufferedInputStream;
60 import java.io.FileOutputStream;
61 import java.lang.reflect.Constructor;
62 import java.lang.reflect.InvocationTargetException;
64 import java.util.ArrayList;
65 import java.util.Hashtable;
66 import java.util.StringTokenizer;
67 import java.util.Vector;
68 import java.util.concurrent.ExecutorService;
69 import java.util.concurrent.Executors;
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, jalview.api.StructureSelectionManagerProvider
102 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
105 * news reader - null if it was never started.
107 private BlogReader jvnews=null;
111 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
113 public void addJalviewPropertyChangeListener(
114 PropertyChangeListener listener)
116 changeSupport.addJalviewPropertyChangeListener(listener);
120 * @param propertyName
122 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
123 * java.beans.PropertyChangeListener)
125 public void addJalviewPropertyChangeListener(String propertyName,
126 PropertyChangeListener listener)
128 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
132 * @param propertyName
134 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
135 * java.beans.PropertyChangeListener)
137 public void removeJalviewPropertyChangeListener(String propertyName,
138 PropertyChangeListener listener)
140 changeSupport.removeJalviewPropertyChangeListener(propertyName,
144 /** Singleton Desktop instance */
145 public static Desktop instance;
147 public static MyDesktopPane desktop;
149 static int openFrameCount = 0;
151 static final int xOffset = 30;
153 static final int yOffset = 30;
155 public static jalview.ws.jws1.Discoverer discoverer;
157 public static Object[] jalviewClipboard;
159 public static boolean internalCopy = false;
161 static int fileLoadingCount = 0;
163 class MyDesktopManager implements DesktopManager
166 private DesktopManager delegate;
168 public MyDesktopManager(DesktopManager delegate)
170 this.delegate = delegate;
173 public void activateFrame(JInternalFrame f)
177 delegate.activateFrame(f);
178 } catch (NullPointerException npe)
180 Point p = getMousePosition();
181 instance.showPasteMenu(p.x, p.y);
185 public void beginDraggingFrame(JComponent f)
187 delegate.beginDraggingFrame(f);
190 public void beginResizingFrame(JComponent f, int direction)
192 delegate.beginResizingFrame(f, direction);
195 public void closeFrame(JInternalFrame f)
197 delegate.closeFrame(f);
200 public void deactivateFrame(JInternalFrame f)
202 delegate.deactivateFrame(f);
205 public void deiconifyFrame(JInternalFrame f)
207 delegate.deiconifyFrame(f);
210 public void dragFrame(JComponent f, int newX, int newY)
216 delegate.dragFrame(f, newX, newY);
219 public void endDraggingFrame(JComponent f)
221 delegate.endDraggingFrame(f);
224 public void endResizingFrame(JComponent f)
226 delegate.endResizingFrame(f);
229 public void iconifyFrame(JInternalFrame f)
231 delegate.iconifyFrame(f);
234 public void maximizeFrame(JInternalFrame f)
236 delegate.maximizeFrame(f);
239 public void minimizeFrame(JInternalFrame f)
241 delegate.minimizeFrame(f);
244 public void openFrame(JInternalFrame f)
246 delegate.openFrame(f);
249 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
252 Rectangle b=desktop.getBounds();
257 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
260 public void setBoundsForFrame(JComponent f, int newX, int newY,
261 int newWidth, int newHeight)
263 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
266 // All other methods, simply delegate
271 * Creates a new Desktop object.
276 * A note to implementors. It is ESSENTIAL that any activities that might
277 * block are spawned off as threads rather than waited for during this
281 doVamsasClientCheck();
284 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
285 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
286 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
288 boolean showjconsole = jalview.bin.Cache.getDefault(
289 "SHOW_JAVA_CONSOLE", false);
290 desktop = new MyDesktopPane(selmemusage);
291 showMemusage.setSelected(selmemusage);
292 desktop.setBackground(Color.white);
293 getContentPane().setLayout(new BorderLayout());
294 // alternate config - have scrollbars - see notes in JAL-153
295 //JScrollPane sp = new JScrollPane();
296 //sp.getViewport().setView(desktop);
297 //getContentPane().add(sp, BorderLayout.CENTER);
298 getContentPane().add(desktop, BorderLayout.CENTER);
299 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() {
422 Cache.log.debug("Starting news thread.");
424 jvnews = new BlogReader(me);
425 showNews.setVisible(true);
426 Cache.log.debug("Completed news thread.");
430 protected void showNews_actionPerformed(ActionEvent e)
432 showNews(showNews.isSelected());
434 void showNews(boolean visible)
437 Cache.log.debug((visible?"Showing":"Hiding")+" news.");
438 showNews.setSelected(visible);
439 if (visible && !jvnews.isVisible())
441 new Thread(new Runnable() {
445 long instance=System.currentTimeMillis();
446 Desktop.instance.setProgressBar("Refreshing news", instance);
447 jvnews.refreshNews();
448 Desktop.instance.setProgressBar(null, instance);
457 * recover the last known dimensions for a jalview window
460 * - empty string is desktop, all other windows have unique prefix
461 * @return null or last known dimensions scaled to current geometry (if last
462 * window geom was known)
464 Rectangle getLastKnownDimensions(String windowName)
466 // TODO: lock aspect ratio for scaling desktop Bug #0058199
467 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
468 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
469 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
470 String width = jalview.bin.Cache.getProperty(windowName
472 String height = jalview.bin.Cache.getProperty(windowName
474 if ((x != null) && (y != null) && (width != null) && (height != null))
476 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
477 .parseInt(width), ih = Integer.parseInt(height);
478 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
480 // attempt #1 - try to cope with change in screen geometry - this
481 // version doesn't preserve original jv aspect ratio.
482 // take ratio of current screen size vs original screen size.
483 double sw = ((1f * screenSize.width) / (1f * Integer
484 .parseInt(jalview.bin.Cache
485 .getProperty("SCREENGEOMETRY_WIDTH"))));
486 double sh = ((1f * screenSize.height) / (1f * Integer
487 .parseInt(jalview.bin.Cache
488 .getProperty("SCREENGEOMETRY_HEIGHT"))));
489 // rescale the bounds depending upon the current screen geometry.
490 ix = (int) (ix * sw);
491 iw = (int) (iw * sw);
492 iy = (int) (iy * sh);
493 ih = (int) (ih * sh);
494 while (ix >= screenSize.width)
496 jalview.bin.Cache.log
497 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
498 ix -= screenSize.width;
500 while (iy >= screenSize.height)
502 jalview.bin.Cache.log
503 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
504 iy -= screenSize.height;
506 jalview.bin.Cache.log.debug("Got last known dimensions for "
507 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
510 // return dimensions for new instance
511 return new Rectangle(ix, iy, iw, ih);
516 private void doVamsasClientCheck()
518 if (jalview.bin.Cache.vamsasJarsPresent())
520 setupVamsasDisconnectedGui();
521 VamsasMenu.setVisible(true);
522 final Desktop us = this;
523 VamsasMenu.addMenuListener(new MenuListener()
525 // this listener remembers when the menu was first selected, and
526 // doesn't rebuild the session list until it has been cleared and
528 boolean refresh = true;
530 public void menuCanceled(MenuEvent e)
535 public void menuDeselected(MenuEvent e)
540 public void menuSelected(MenuEvent e)
544 us.buildVamsasStMenu();
549 vamsasStart.setVisible(true);
553 void showPasteMenu(int x, int y)
555 JPopupMenu popup = new JPopupMenu();
556 JMenuItem item = new JMenuItem("Paste To New Window");
557 item.addActionListener(new ActionListener()
559 public void actionPerformed(ActionEvent evt)
566 popup.show(this, x, y);
573 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
574 Transferable contents = c.getContents(this);
576 if (contents != null)
578 String file = (String) contents
579 .getTransferData(DataFlavor.stringFlavor);
581 String format = new IdentifyFile().Identify(file,
582 FormatAdapter.PASTE);
584 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
587 } catch (Exception ex)
590 .println("Unable to paste alignment from system clipboard:\n"
596 * Adds and opens the given frame to the desktop
607 public static synchronized void addInternalFrame(
608 final JInternalFrame frame, String title, int w, int h)
610 addInternalFrame(frame, title, w, h, true);
627 public static synchronized void addInternalFrame(
628 final JInternalFrame frame, String title, int w, int h,
632 // TODO: allow callers to determine X and Y position of frame (eg. via
634 // TODO: consider fixing method to update entries in the window submenu with
635 // the current window title
637 frame.setTitle(title);
638 if (frame.getWidth() < 1 || frame.getHeight() < 1)
642 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
643 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
644 // IF JALVIEW IS RUNNING HEADLESS
645 // ///////////////////////////////////////////////
646 if (System.getProperty("java.awt.headless") != null
647 && System.getProperty("java.awt.headless").equals("true"))
654 frame.setVisible(true);
655 frame.setClosable(true);
656 frame.setResizable(resizable);
657 frame.setMaximizable(resizable);
658 frame.setIconifiable(resizable);
659 frame.setFrameIcon(null);
661 if (frame.getX() < 1 && frame.getY() < 1)
663 frame.setLocation(xOffset * openFrameCount, yOffset
664 * ((openFrameCount - 1) % 10) + yOffset);
667 final JMenuItem menuItem = new JMenuItem(title);
668 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
670 public void internalFrameActivated(
671 javax.swing.event.InternalFrameEvent evt)
673 JInternalFrame itf = desktop.getSelectedFrame();
681 public void internalFrameClosed(
682 javax.swing.event.InternalFrameEvent evt)
684 PaintRefresher.RemoveComponent(frame);
686 windowMenu.remove(menuItem);
687 JInternalFrame itf = desktop.getSelectedFrame();
696 menuItem.addActionListener(new ActionListener()
698 public void actionPerformed(ActionEvent e)
702 frame.setSelected(true);
703 frame.setIcon(false);
704 } catch (java.beans.PropertyVetoException ex)
710 menuItem.addMouseListener(new MouseListener()
714 public void mouseReleased(MouseEvent e)
719 public void mousePressed(MouseEvent e)
724 public void mouseExited(MouseEvent e)
728 frame.setSelected(false);
729 } catch (PropertyVetoException e1)
735 public void mouseEntered(MouseEvent e)
739 frame.setSelected(true);
740 } catch (PropertyVetoException e1)
746 public void mouseClicked(MouseEvent e)
752 windowMenu.add(menuItem);
758 frame.setSelected(true);
759 frame.requestFocus();
760 } catch (java.beans.PropertyVetoException ve)
763 catch (java.lang.ClassCastException cex)
765 Cache.log.warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",cex);
769 public void lostOwnership(Clipboard clipboard, Transferable contents)
773 Desktop.jalviewClipboard = null;
776 internalCopy = false;
779 public void dragEnter(DropTargetDragEvent evt)
783 public void dragExit(DropTargetEvent evt)
787 public void dragOver(DropTargetDragEvent evt)
791 public void dropActionChanged(DropTargetDragEvent evt)
801 public void drop(DropTargetDropEvent evt)
803 Transferable t = evt.getTransferable();
804 java.util.List files = null;
805 java.util.List protocols = null;
809 DataFlavor uriListFlavor = new DataFlavor(
810 "text/uri-list;class=java.lang.String");
811 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
813 // Works on Windows and MacOSX
814 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
815 files = (java.util.List) t
816 .getTransferData(DataFlavor.javaFileListFlavor);
818 else if (t.isDataFlavorSupported(uriListFlavor))
820 // This is used by Unix drag system
821 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
822 String data = (String) t.getTransferData(uriListFlavor);
823 files = new java.util.ArrayList(1);
824 protocols = new java.util.ArrayList(1);
825 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
826 data, "\r\n"); st.hasMoreTokens();)
828 String s = st.nextToken();
829 if (s.startsWith("#"))
831 // the line is a comment (as per the RFC 2483)
834 java.net.URI uri = new java.net.URI(s);
835 if (uri.getScheme().toLowerCase().startsWith("http"))
837 protocols.add(FormatAdapter.URL);
838 files.add(uri.toString());
842 // otherwise preserve old behaviour: catch all for file objects
843 java.io.File file = new java.io.File(uri);
844 protocols.add(FormatAdapter.FILE);
845 files.add(file.toString());
849 } catch (Exception e)
857 for (int i = 0; i < files.size(); i++)
859 String file = files.get(i).toString();
860 String protocol = (protocols == null) ? FormatAdapter.FILE
861 : (String) protocols.get(i);
862 String format = null;
864 if (file.endsWith(".jar"))
871 format = new IdentifyFile().Identify(file, protocol);
874 new FileLoader().LoadFile(file, protocol, format);
877 } catch (Exception ex)
889 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
891 JalviewFileChooser chooser = new JalviewFileChooser(
892 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
893 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
894 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
895 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
897 chooser.setFileView(new JalviewFileView());
898 chooser.setDialogTitle("Open local file");
899 chooser.setToolTipText("Open");
901 int value = chooser.showOpenDialog(this);
903 if (value == JalviewFileChooser.APPROVE_OPTION)
905 String choice = chooser.getSelectedFile().getPath();
906 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
907 .getSelectedFile().getParent());
909 String format = null;
910 if (chooser.getSelectedFormat().equals("Jalview"))
916 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
919 if (viewport != null)
921 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
926 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
937 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
939 // This construct allows us to have a wider textfield
941 JLabel label = new JLabel("Enter URL of Input File");
942 final JComboBox history = new JComboBox();
944 JPanel panel = new JPanel(new GridLayout(2, 1));
947 history.setPreferredSize(new Dimension(400, 20));
948 history.setEditable(true);
949 history.addItem("http://www.");
951 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
955 if (historyItems != null)
957 st = new StringTokenizer(historyItems, "\t");
959 while (st.hasMoreTokens())
961 history.addItem(st.nextElement());
965 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
966 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
968 if (reply != JOptionPane.OK_OPTION)
973 String url = history.getSelectedItem().toString();
975 if (url.toLowerCase().endsWith(".jar"))
977 if (viewport != null)
979 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
984 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
989 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
991 if (format.equals("URL NOT FOUND"))
993 JOptionPane.showInternalMessageDialog(Desktop.desktop,
994 "Couldn't locate " + url, "URL not found",
995 JOptionPane.WARNING_MESSAGE);
1000 if (viewport != null)
1002 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1006 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1017 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1019 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1020 cap.setForInput(viewport);
1021 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1029 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1031 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1032 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1034 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1035 getBounds().y, getWidth(), getHeight()));
1037 if (jconsole != null)
1039 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1040 jconsole.stopConsole();
1044 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1047 if (dialogExecutor!=null)
1049 dialogExecutor.shutdownNow();
1055 private void storeLastKnownDimensions(String string, Rectangle jc)
1057 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1058 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1059 + " height:" + jc.height);
1061 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1062 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1063 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1064 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1073 public void aboutMenuItem_actionPerformed(ActionEvent e)
1075 // StringBuffer message = getAboutMessage(false);
1076 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1078 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1079 new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
1082 public StringBuffer getAboutMessage(boolean shortv)
1084 StringBuffer message = new StringBuffer();
1085 message.append("<html>");
1088 message.append("<h1><strong>Version: "
1089 + jalview.bin.Cache.getProperty("VERSION")
1090 + "</strong></h1><br>");
1091 message.append("<strong>Last Updated: <em>"
1092 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1093 + "</em></strong>");
1099 message.append("<strong>Version "
1100 + jalview.bin.Cache.getProperty("VERSION")
1101 + "; last updated: "
1102 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1105 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1108 message.append("<br>...Checking latest version...</br>");
1110 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1111 .equals(jalview.bin.Cache.getProperty("VERSION")))
1113 boolean red = false;
1114 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1115 .indexOf("automated build") == -1)
1118 // Displayed when code version and jnlp version do not match and code
1119 // version is not a development build
1120 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1123 message.append("<br>!! Version "
1124 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1126 + " is available for download from "
1127 + jalview.bin.Cache.getDefault("www.jalview.org",
1128 "http://www.jalview.org") + " !!");
1131 message.append("</div>");
1134 message.append("<br>Authors: "
1138 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1139 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1140 + "<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"
1141 + "<br>If you use Jalview, please cite:"
1142 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1143 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1144 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1155 public void documentationMenuItem_actionPerformed(ActionEvent e)
1159 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1160 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1161 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1163 javax.help.HelpBroker hb = hs.createHelpBroker();
1164 hb.setCurrentID("home");
1165 hb.setDisplayed(true);
1166 } catch (Exception ex)
1171 public void closeAll_actionPerformed(ActionEvent e)
1173 JInternalFrame[] frames = desktop.getAllFrames();
1174 for (int i = 0; i < frames.length; i++)
1178 frames[i].setClosed(true);
1179 } catch (java.beans.PropertyVetoException ex)
1183 System.out.println("ALL CLOSED");
1184 if (v_client != null)
1186 // TODO clear binding to vamsas document objects on close_all
1191 public void raiseRelated_actionPerformed(ActionEvent e)
1193 reorderAssociatedWindows(false, false);
1196 public void minimizeAssociated_actionPerformed(ActionEvent e)
1198 reorderAssociatedWindows(true, false);
1201 void closeAssociatedWindows()
1203 reorderAssociatedWindows(false, true);
1209 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1212 protected void garbageCollect_actionPerformed(ActionEvent e)
1214 // We simply collect the garbage
1215 jalview.bin.Cache.log.debug("Collecting garbage...");
1217 jalview.bin.Cache.log.debug("Finished garbage collection.");
1224 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1227 protected void showMemusage_actionPerformed(ActionEvent e)
1229 desktop.showMemoryUsage(showMemusage.isSelected());
1236 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1239 protected void showConsole_actionPerformed(ActionEvent e)
1241 showConsole(showConsole.isSelected());
1244 Console jconsole = null;
1247 * control whether the java console is visible or not
1251 void showConsole(boolean selected)
1253 showConsole.setSelected(selected);
1254 // TODO: decide if we should update properties file
1255 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1257 jconsole.setVisible(selected);
1260 void reorderAssociatedWindows(boolean minimize, boolean close)
1262 JInternalFrame[] frames = desktop.getAllFrames();
1263 if (frames == null || frames.length < 1)
1268 AlignViewport source = null, target = null;
1269 if (frames[0] instanceof AlignFrame)
1271 source = ((AlignFrame) frames[0]).getCurrentView();
1273 else if (frames[0] instanceof TreePanel)
1275 source = ((TreePanel) frames[0]).getViewPort();
1277 else if (frames[0] instanceof PCAPanel)
1279 source = ((PCAPanel) frames[0]).av;
1281 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1283 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1288 for (int i = 0; i < frames.length; i++)
1291 if (frames[i] == null)
1295 if (frames[i] instanceof AlignFrame)
1297 target = ((AlignFrame) frames[i]).getCurrentView();
1299 else if (frames[i] instanceof TreePanel)
1301 target = ((TreePanel) frames[i]).getViewPort();
1303 else if (frames[i] instanceof PCAPanel)
1305 target = ((PCAPanel) frames[i]).av;
1307 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1309 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1312 if (source == target)
1318 frames[i].setClosed(true);
1322 frames[i].setIcon(minimize);
1325 frames[i].toFront();
1329 } catch (java.beans.PropertyVetoException ex)
1343 protected void preferences_actionPerformed(ActionEvent e)
1354 public void saveState_actionPerformed(ActionEvent e)
1356 JalviewFileChooser chooser = new JalviewFileChooser(
1357 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1358 { "jar" }, new String[]
1359 { "Jalview Project" }, "Jalview Project");
1361 chooser.setFileView(new JalviewFileView());
1362 chooser.setDialogTitle("Save State");
1364 int value = chooser.showSaveDialog(this);
1366 if (value == JalviewFileChooser.APPROVE_OPTION)
1368 final Desktop me = this;
1369 final java.io.File choice = chooser.getSelectedFile();
1370 new Thread(new Runnable()
1375 setProgressBar("Saving jalview project " + choice.getName(),
1377 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1378 // TODO catch and handle errors for savestate
1379 // TODO prevent user from messing with the Desktop whilst we're saving
1382 new Jalview2XML().SaveState(choice);
1383 } catch (OutOfMemoryError oom)
1386 "Whilst saving current state to " + choice.getName(), oom);
1387 } catch (Exception ex)
1390 .error("Problems whilst trying to save to "
1391 + choice.getName(), ex);
1392 JOptionPane.showMessageDialog(me,
1393 "Error whilst saving current state to " + choice.getName(),
1394 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1396 setProgressBar(null, choice.hashCode());
1408 public void loadState_actionPerformed(ActionEvent e)
1410 JalviewFileChooser chooser = new JalviewFileChooser(
1411 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1412 { "jar" }, new String[]
1413 { "Jalview Project" }, "Jalview Project");
1414 chooser.setFileView(new JalviewFileView());
1415 chooser.setDialogTitle("Restore state");
1417 int value = chooser.showOpenDialog(this);
1419 if (value == JalviewFileChooser.APPROVE_OPTION)
1421 final String choice = chooser.getSelectedFile().getAbsolutePath();
1422 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1423 .getSelectedFile().getParent());
1424 new Thread(new Runnable()
1428 setProgressBar("loading jalview project " + choice,
1432 new Jalview2XML().LoadJalviewAlign(choice);
1433 } catch (OutOfMemoryError oom)
1435 new OOMWarning("Whilst loading project from " + choice, oom);
1436 } catch (Exception ex)
1438 Cache.log.error("Problems whilst loading project from "
1440 JOptionPane.showMessageDialog(Desktop.desktop,
1441 "Error whilst loading project from " + choice,
1442 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1444 setProgressBar(null, choice.hashCode());
1450 public void inputSequence_actionPerformed(ActionEvent e)
1452 new SequenceFetcher(this);
1455 JPanel progressPanel;
1456 ArrayList<JPanel> fileLoadingPanels=new ArrayList<JPanel>();
1457 public void startLoading(final String fileName)
1459 if (fileLoadingCount == 0)
1461 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName + " "));
1466 private JPanel addProgressPanel(String string)
1468 if (progressPanel == null)
1470 progressPanel = new JPanel(new GridLayout(1,1));
1471 totalProgressCount = 0;
1472 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1474 JPanel thisprogress=new JPanel(new BorderLayout(10,5));
1475 JProgressBar progressBar = new JProgressBar();
1476 progressBar.setIndeterminate(true);
1478 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1480 thisprogress.add(progressBar, BorderLayout.CENTER);
1481 progressPanel.add(thisprogress);
1482 ((GridLayout)progressPanel.getLayout()).setRows(((GridLayout)progressPanel.getLayout()).getRows()+1);
1483 ++totalProgressCount;
1484 instance.validate();
1485 return thisprogress;
1488 int totalProgressCount = 0;
1490 private void removeProgressPanel(JPanel progbar)
1492 if (progressPanel != null)
1494 progressPanel.remove(progbar);
1495 GridLayout gl = (GridLayout) progressPanel.getLayout();
1496 gl.setRows(gl.getRows()-1);
1497 if (--totalProgressCount < 1)
1499 this.getContentPane().remove(progressPanel);
1500 progressPanel = null;
1506 public void stopLoading()
1509 if (fileLoadingCount < 1)
1511 for (JPanel flp : fileLoadingPanels)
1513 removeProgressPanel(flp);
1515 fileLoadingPanels.clear();
1516 fileLoadingCount = 0;
1521 public static int getViewCount(String alignmentId)
1523 AlignViewport[] aps = getViewports(alignmentId);
1524 return (aps == null) ? 0 : aps.length;
1529 * @param alignmentId
1530 * @return all AlignmentPanels concerning the alignmentId sequence set
1532 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1535 if (Desktop.desktop == null)
1537 // no frames created and in headless mode
1538 // TODO: verify that frames are recoverable when in headless mode
1541 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1542 ArrayList aps = new ArrayList();
1543 for (int t = 0; t < frames.length; t++)
1545 if (frames[t] instanceof AlignFrame)
1547 AlignFrame af = (AlignFrame) frames[t];
1548 for (int a = 0; a < af.alignPanels.size(); a++)
1551 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1552 .getSequenceSetId()))
1554 aps.add(af.alignPanels.elementAt(a));
1559 if (aps.size() == 0)
1563 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1564 for (int t = 0; t < vap.length; t++)
1566 vap[t] = (AlignmentPanel) aps.get(t);
1572 * get all the viewports on an alignment.
1574 * @param sequenceSetId
1575 * unique alignment id
1576 * @return all viewports on the alignment bound to sequenceSetId
1578 public static AlignViewport[] getViewports(String sequenceSetId)
1580 Vector viewp = new Vector();
1581 if (desktop != null)
1583 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1585 for (int t = 0; t < frames.length; t++)
1587 if (frames[t] instanceof AlignFrame)
1589 AlignFrame afr = ((AlignFrame) frames[t]);
1590 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1592 if (afr.alignPanels != null)
1594 for (int a = 0; a < afr.alignPanels.size(); a++)
1596 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1597 .elementAt(a)).av.getSequenceSetId()))
1599 viewp.addElement(((AlignmentPanel) afr.alignPanels
1606 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1611 if (viewp.size() > 0)
1613 AlignViewport[] vp = new AlignViewport[viewp.size()];
1621 public void explodeViews(AlignFrame af)
1623 int size = af.alignPanels.size();
1629 for (int i = 0; i < size; i++)
1631 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1632 AlignFrame newaf = new AlignFrame(ap);
1633 if (ap.av.explodedPosition != null
1634 && !ap.av.explodedPosition.equals(af.getBounds()))
1636 newaf.setBounds(ap.av.explodedPosition);
1639 ap.av.gatherViewsHere = false;
1641 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1642 AlignFrame.DEFAULT_HEIGHT);
1645 af.alignPanels.clear();
1646 af.closeMenuItem_actionPerformed(true);
1650 public void gatherViews(AlignFrame source)
1652 source.viewport.gatherViewsHere = true;
1653 source.viewport.explodedPosition = source.getBounds();
1654 JInternalFrame[] frames = desktop.getAllFrames();
1655 String viewId = source.viewport.getSequenceSetId();
1657 for (int t = 0; t < frames.length; t++)
1659 if (frames[t] instanceof AlignFrame && frames[t] != source)
1661 AlignFrame af = (AlignFrame) frames[t];
1662 boolean gatherThis = false;
1663 for (int a = 0; a < af.alignPanels.size(); a++)
1665 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1666 if (viewId.equals(ap.av.getSequenceSetId()))
1669 ap.av.gatherViewsHere = false;
1670 ap.av.explodedPosition = af.getBounds();
1671 source.addAlignmentPanel(ap, false);
1677 af.alignPanels.clear();
1678 af.closeMenuItem_actionPerformed(true);
1685 jalview.gui.VamsasApplication v_client = null;
1687 public void vamsasImport_actionPerformed(ActionEvent e)
1689 if (v_client == null)
1691 // Load and try to start a session.
1692 JalviewFileChooser chooser = new JalviewFileChooser(
1693 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1695 chooser.setFileView(new JalviewFileView());
1696 chooser.setDialogTitle("Open a saved VAMSAS session");
1697 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1699 int value = chooser.showOpenDialog(this);
1701 if (value == JalviewFileChooser.APPROVE_OPTION)
1703 String fle = chooser.getSelectedFile().toString();
1704 if (!vamsasImport(chooser.getSelectedFile()))
1706 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1707 "Couldn't import '" + fle + "' as a new vamsas session.",
1708 "Vamsas Document Import Failed",
1709 JOptionPane.ERROR_MESSAGE);
1715 jalview.bin.Cache.log
1716 .error("Implementation error - load session from a running session is not supported.");
1721 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1724 * @return true if import was a success and a session was started.
1726 public boolean vamsasImport(URL url)
1728 // TODO: create progress bar
1729 if (v_client != null)
1732 jalview.bin.Cache.log
1733 .error("Implementation error - load session from a running session is not supported.");
1739 // copy the URL content to a temporary local file
1740 // TODO: be a bit cleverer here with nio (?!)
1741 File file = File.createTempFile("vdocfromurl", ".vdj");
1742 FileOutputStream fos = new FileOutputStream(file);
1743 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1744 byte[] buffer = new byte[2048];
1746 while ((ln = bis.read(buffer)) > -1)
1748 fos.write(buffer, 0, ln);
1752 v_client = new jalview.gui.VamsasApplication(this, file,
1753 url.toExternalForm());
1754 } catch (Exception ex)
1756 jalview.bin.Cache.log.error(
1757 "Failed to create new vamsas session from contents of URL "
1761 setupVamsasConnectedGui();
1762 v_client.initial_update(); // TODO: thread ?
1763 return v_client.inSession();
1767 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1770 * @return true if import was a success and a session was started.
1772 public boolean vamsasImport(File file)
1774 if (v_client != null)
1777 jalview.bin.Cache.log
1778 .error("Implementation error - load session from a running session is not supported.");
1782 setProgressBar("Importing VAMSAS session from " + file.getName(),
1786 v_client = new jalview.gui.VamsasApplication(this, file, null);
1787 } catch (Exception ex)
1789 setProgressBar("Importing VAMSAS session from " + file.getName(),
1791 jalview.bin.Cache.log.error(
1792 "New vamsas session from existing session file failed:", ex);
1795 setupVamsasConnectedGui();
1796 v_client.initial_update(); // TODO: thread ?
1797 setProgressBar("Importing VAMSAS session from " + file.getName(),
1799 return v_client.inSession();
1802 public boolean joinVamsasSession(String mysesid)
1804 if (v_client != null)
1807 "Trying to join a vamsas session when another is already connected.");
1809 if (mysesid == null)
1811 throw new Error("Invalid vamsas session id.");
1813 v_client = new VamsasApplication(this, mysesid);
1814 setupVamsasConnectedGui();
1815 v_client.initial_update();
1816 return (v_client.inSession());
1819 public void vamsasStart_actionPerformed(ActionEvent e)
1821 if (v_client == null)
1824 // we just start a default session for moment.
1826 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1827 * getProperty("LAST_DIRECTORY"));
1829 * chooser.setFileView(new JalviewFileView());
1830 * chooser.setDialogTitle("Load Vamsas file");
1831 * chooser.setToolTipText("Import");
1833 * int value = chooser.showOpenDialog(this);
1835 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1836 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1838 v_client = new VamsasApplication(this);
1839 setupVamsasConnectedGui();
1840 v_client.initial_update(); // TODO: thread ?
1844 // store current data in session.
1845 v_client.push_update(); // TODO: thread
1849 protected void setupVamsasConnectedGui()
1851 vamsasStart.setText("Session Update");
1852 vamsasSave.setVisible(true);
1853 vamsasStop.setVisible(true);
1854 vamsasImport.setVisible(false); // Document import to existing session is
1855 // not possible for vamsas-client-1.0.
1858 protected void setupVamsasDisconnectedGui()
1860 vamsasSave.setVisible(false);
1861 vamsasStop.setVisible(false);
1862 vamsasImport.setVisible(true);
1863 vamsasStart.setText("New Vamsas Session");
1866 public void vamsasStop_actionPerformed(ActionEvent e)
1868 if (v_client != null)
1870 v_client.end_session();
1872 setupVamsasDisconnectedGui();
1876 protected void buildVamsasStMenu()
1878 if (v_client == null)
1880 String[] sess = null;
1883 sess = VamsasApplication.getSessionList();
1884 } catch (Exception e)
1886 jalview.bin.Cache.log.warn(
1887 "Problem getting current sessions list.", e);
1892 jalview.bin.Cache.log.debug("Got current sessions list: "
1893 + sess.length + " entries.");
1894 VamsasStMenu.removeAll();
1895 for (int i = 0; i < sess.length; i++)
1897 JMenuItem sessit = new JMenuItem();
1898 sessit.setText(sess[i]);
1899 sessit.setToolTipText("Connect to session " + sess[i]);
1900 final Desktop dsktp = this;
1901 final String mysesid = sess[i];
1902 sessit.addActionListener(new ActionListener()
1905 public void actionPerformed(ActionEvent e)
1907 if (dsktp.v_client == null)
1909 Thread rthr = new Thread(new Runnable()
1914 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1915 dsktp.setupVamsasConnectedGui();
1916 dsktp.v_client.initial_update();
1924 VamsasStMenu.add(sessit);
1926 // don't show an empty menu.
1927 VamsasStMenu.setVisible(sess.length > 0);
1932 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1933 VamsasStMenu.removeAll();
1934 VamsasStMenu.setVisible(false);
1939 // Not interested in the content. Just hide ourselves.
1940 VamsasStMenu.setVisible(false);
1944 public void vamsasSave_actionPerformed(ActionEvent e)
1946 if (v_client != null)
1948 JalviewFileChooser chooser = new JalviewFileChooser(
1949 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1950 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1952 { "Vamsas Document" }, "Vamsas Document");
1954 chooser.setFileView(new JalviewFileView());
1955 chooser.setDialogTitle("Save Vamsas Document Archive");
1957 int value = chooser.showSaveDialog(this);
1959 if (value == JalviewFileChooser.APPROVE_OPTION)
1961 java.io.File choice = chooser.getSelectedFile();
1962 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1963 + choice.getName());
1964 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1965 String warnmsg = null;
1966 String warnttl = null;
1969 v_client.vclient.storeDocument(choice);
1972 warnttl = "Serious Problem saving Vamsas Document";
1973 warnmsg = ex.toString();
1974 jalview.bin.Cache.log.error("Error Whilst saving document to "
1977 } catch (Exception ex)
1979 warnttl = "Problem saving Vamsas Document.";
1980 warnmsg = ex.toString();
1981 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1985 removeProgressPanel(progpanel);
1986 if (warnmsg != null)
1988 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1990 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1996 JPanel vamUpdate = null;
1999 * hide vamsas user gui bits when a vamsas document event is being handled.
2002 * true to hide gui, false to reveal gui
2004 public void setVamsasUpdate(boolean b)
2006 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2007 + (b ? "in progress" : "finished"));
2009 if (vamUpdate != null)
2011 this.removeProgressPanel(vamUpdate);
2015 vamUpdate = this.addProgressPanel("Updating vamsas session");
2017 vamsasStart.setVisible(!b);
2018 vamsasStop.setVisible(!b);
2019 vamsasSave.setVisible(!b);
2022 public JInternalFrame[] getAllFrames()
2024 return desktop.getAllFrames();
2028 * Checks the given url to see if it gives a response indicating that the user
2029 * should be informed of a new questionnaire.
2033 public void checkForQuestionnaire(String url)
2035 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2036 // javax.swing.SwingUtilities.invokeLater(jvq);
2037 new Thread(jvq).start();
2041 * Proxy class for JDesktopPane which optionally displays the current memory
2042 * usage and highlights the desktop area with a red bar if free memory runs
2047 public class MyDesktopPane extends JDesktopPane implements Runnable
2050 boolean showMemoryUsage = false;
2054 java.text.NumberFormat df;
2056 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2059 public MyDesktopPane(boolean showMemoryUsage)
2061 showMemoryUsage(showMemoryUsage);
2064 public void showMemoryUsage(boolean showMemoryUsage)
2066 this.showMemoryUsage = showMemoryUsage;
2067 if (showMemoryUsage)
2069 Thread worker = new Thread(this);
2074 public boolean isShowMemoryUsage()
2076 return showMemoryUsage;
2081 df = java.text.NumberFormat.getNumberInstance();
2082 df.setMaximumFractionDigits(2);
2083 runtime = Runtime.getRuntime();
2085 while (showMemoryUsage)
2089 maxMemory = runtime.maxMemory() / 1048576f;
2090 allocatedMemory = runtime.totalMemory() / 1048576f;
2091 freeMemory = runtime.freeMemory() / 1048576f;
2092 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2094 percentUsage = (totalFreeMemory / maxMemory) * 100;
2096 // if (percentUsage < 20)
2098 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2100 // instance.set.setBorder(border1);
2103 // sleep after showing usage
2105 } catch (Exception ex)
2107 ex.printStackTrace();
2112 public void paintComponent(Graphics g)
2114 if (showMemoryUsage && g != null && df != null)
2116 if (percentUsage < 20)
2117 g.setColor(Color.red);
2118 FontMetrics fm = g.getFontMetrics();
2122 "Total Free Memory: " + df.format(totalFreeMemory)
2123 + "MB; Max Memory: " + df.format(maxMemory)
2124 + "MB; " + df.format(percentUsage) + "%", 10,
2125 getHeight() - fm.getHeight());
2132 * fixes stacking order after a modal dialog to ensure windows that should be on top actually are
2134 public void relayerWindows()
2139 protected JMenuItem groovyShell;
2141 public void doGroovyCheck()
2143 if (jalview.bin.Cache.groovyJarsPresent())
2145 groovyShell = new JMenuItem();
2146 groovyShell.setText("Groovy Console...");
2147 groovyShell.addActionListener(new ActionListener()
2149 public void actionPerformed(ActionEvent e)
2151 groovyShell_actionPerformed(e);
2154 toolsMenu.add(groovyShell);
2155 groovyShell.setVisible(true);
2160 * Accessor method to quickly get all the AlignmentFrames loaded.
2162 public static AlignFrame[] getAlignframes()
2164 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2170 Vector avp = new Vector();
2174 for (int i = frames.length - 1; i > -1; i--)
2176 if (frames[i] instanceof AlignFrame)
2178 AlignFrame af = (AlignFrame) frames[i];
2182 } catch (Exception ex)
2184 ex.printStackTrace();
2186 if (avp.size() == 0)
2190 AlignFrame afs[] = new AlignFrame[avp.size()];
2191 for (int i = 0, j = avp.size(); i < j; i++)
2193 afs[i] = (AlignFrame) avp.elementAt(i);
2198 public AppJmol[] getJmols()
2200 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2206 Vector avp = new Vector();
2210 for (int i = frames.length - 1; i > -1; i--)
2212 if (frames[i] instanceof AppJmol)
2214 AppJmol af = (AppJmol) frames[i];
2218 } catch (Exception ex)
2220 ex.printStackTrace();
2222 if (avp.size() == 0)
2226 AppJmol afs[] = new AppJmol[avp.size()];
2227 for (int i = 0, j = avp.size(); i < j; i++)
2229 afs[i] = (AppJmol) avp.elementAt(i);
2236 * Add Groovy Support to Jalview
2238 public void groovyShell_actionPerformed(ActionEvent e)
2240 // use reflection to avoid creating compilation dependency.
2241 if (!jalview.bin.Cache.groovyJarsPresent())
2244 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2248 Class gcClass = Desktop.class.getClassLoader().loadClass(
2249 "groovy.ui.Console");
2250 Constructor gccons = gcClass.getConstructor(null);
2251 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2253 { String.class, Object.class });
2254 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2255 Object gc = gccons.newInstance(null);
2256 setvar.invoke(gc, new Object[]
2257 { "Jalview", this });
2258 run.invoke(gc, null);
2259 } catch (Exception ex)
2261 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2263 .showInternalMessageDialog(
2266 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2267 "Jalview Groovy Support Failed",
2268 JOptionPane.ERROR_MESSAGE);
2273 * Progress bars managed by the IProgressIndicator method.
2275 private Hashtable<Long,JPanel> progressBars;
2276 private Hashtable<Long,IProgressIndicatorHandler> progressBarHandlers;
2281 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2283 public void setProgressBar(String message, long id)
2285 if (progressBars == null)
2287 progressBars = new Hashtable<Long,JPanel>();
2288 progressBarHandlers = new Hashtable<Long,IProgressIndicatorHandler>();
2291 if (progressBars.get(new Long(id)) != null)
2293 JPanel progressPanel = progressBars
2294 .remove(new Long(id));
2295 if (progressBarHandlers.contains(new Long(id)))
2297 progressBarHandlers.remove(new Long(id));
2299 removeProgressPanel(progressPanel);
2303 progressBars.put(new Long(id), addProgressPanel(message));
2310 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2311 * jalview.gui.IProgressIndicatorHandler)
2313 public void registerHandler(final long id,
2314 final IProgressIndicatorHandler handler)
2316 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2319 "call setProgressBar before registering the progress bar's handler.");
2321 progressBarHandlers.put(new Long(id), handler);
2322 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2323 if (handler.canCancel())
2325 JButton cancel = new JButton("Cancel");
2326 final IProgressIndicator us = this;
2327 cancel.addActionListener(new ActionListener()
2330 public void actionPerformed(ActionEvent e)
2332 handler.cancelActivity(id);
2335 + ((JLabel) progressPanel.getComponent(0))
2339 progressPanel.add(cancel, BorderLayout.EAST);
2345 * @return true if any progress bars are still active
2348 public boolean operationInProgress()
2350 if (progressBars != null && progressBars.size() > 0)
2358 * This will return the first AlignFrame viewing AlignViewport av. It will
2359 * break if there are more than one AlignFrames viewing a particular av. This
2362 * @return alignFrame for av
2364 public static AlignFrame getAlignFrameFor(AlignViewport av)
2366 if (desktop != null)
2368 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2369 for (int panel = 0; aps != null && panel < aps.length; panel++)
2371 if (aps[panel] != null && aps[panel].av == av)
2373 return aps[panel].alignFrame;
2380 public VamsasApplication getVamsasApplication()
2387 * flag set if jalview GUI is being operated programmatically
2389 private boolean inBatchMode = false;
2392 * check if jalview GUI is being operated programmatically
2394 * @return inBatchMode
2396 public boolean isInBatchMode()
2402 * set flag if jalview GUI is being operated programmatically
2404 * @param inBatchMode
2406 public void setInBatchMode(boolean inBatchMode)
2408 this.inBatchMode = inBatchMode;
2411 public void startServiceDiscovery()
2413 startServiceDiscovery(false);
2416 public void startServiceDiscovery(boolean blocking)
2418 boolean alive = true;
2419 Thread t0 = null, t1 = null, t2 = null;
2421 // todo: changesupport handlers need to be transferred
2422 if (discoverer == null)
2424 discoverer = new jalview.ws.jws1.Discoverer();
2425 // register PCS handler for desktop.
2426 discoverer.addPropertyChangeListener(changeSupport);
2428 // JAL-940 - disabled JWS1 service configuration - always start discoverer until we phase out completely
2431 (t0 = new Thread(discoverer)).start();
2436 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2438 // EnfinEnvision web service menu entries are rebuild every time the
2439 // menu is shown, so no changeSupport events are needed.
2440 jalview.ws.EnfinEnvision2OneWay.getInstance();
2441 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2444 } catch (Exception e)
2447 .info("Exception when trying to launch Envision2 workflow discovery.",
2449 Cache.log.info(e.getStackTrace());
2451 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2453 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2455 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2457 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2463 // TODO: do rest service discovery
2472 } catch (Exception e)
2475 alive = (t1 != null && t1.isAlive())
2476 || (t2 != null && t2.isAlive())
2477 || (t3 != null && t3.isAlive())
2478 || (t0 != null && t0.isAlive());
2484 * called to check if the service discovery process completed successfully.
2488 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2490 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2492 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2493 .getErrorMessages();
2496 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2498 if (serviceChangedDialog == null)
2500 // only run if we aren't already displaying one of these.
2501 javax.swing.SwingUtilities
2502 .invokeLater(serviceChangedDialog = new Runnable()
2508 .showInternalMessageDialog(
2511 + "It may be that you have invalid JABA URLs\nin your web service preferences.\n\nGo to the Web services tab of the\nTools->Preferences dialog box to change them.\n",
2512 "Preferences Problem",
2513 JOptionPane.WARNING_MESSAGE);
2514 serviceChangedDialog = null;
2523 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2530 private Runnable serviceChangedDialog = null;
2533 * start a thread to open a URL in the configured browser. Pops up a warning
2534 * dialog to the user if there is an exception when calling out to the browser
2539 public static void showUrl(final String url)
2541 showUrl(url, Desktop.instance);
2544 * Like showUrl but allows progress handler to be specified
2546 * @param progress (null) or object implementing IProgressIndicator
2548 public static void showUrl(final String url, final IProgressIndicator progress)
2550 new Thread(new Runnable()
2556 if (progress!=null) {
2557 progress.setProgressBar("Opening "+url, this.hashCode());
2559 jalview.util.BrowserLauncher.openURL(url);
2560 } catch (Exception ex)
2563 .showInternalMessageDialog(
2565 "Unixers: Couldn't find default web browser."
2566 + "\nAdd the full path to your browser in Preferences.",
2567 "Web browser not found",
2568 JOptionPane.WARNING_MESSAGE);
2570 ex.printStackTrace();
2572 if (progress!=null) {
2573 progress.setProgressBar(null, this.hashCode());
2579 public static WsParamSetManager wsparamManager = null;
2581 public static ParamManager getUserParameterStore()
2583 if (wsparamManager == null)
2585 wsparamManager = new WsParamSetManager();
2587 return wsparamManager;
2591 * static hyperlink handler proxy method for use by Jalview's internal windows
2594 public static void hyperlinkUpdate(HyperlinkEvent e)
2596 if (e.getEventType() == EventType.ACTIVATED)
2601 url = e.getURL().toString();
2602 Desktop.showUrl(url);
2603 } catch (Exception x)
2606 if (Cache.log!=null) {
2607 Cache.log.error("Couldn't handle string "+url+" as a URL.");
2609 System.err.println("Couldn't handle string "+url+" as a URL.");
2612 // ignore any exceptions due to dud links.
2618 * single thread that handles display of dialogs to user.
2620 ExecutorService dialogExecutor=Executors.newSingleThreadExecutor();
2623 * add another dialog thread to the queue
2626 public void addDialogThread(final Runnable prompter)
2628 dialogExecutor.submit(new Runnable()
2634 SwingUtilities.invokeAndWait(prompter);
2635 } catch (Exception q)
2637 Cache.log.warn("Unexpected Exception in dialog thread.", q);