2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
21 import jalview.io.FileLoader;
22 import jalview.io.FormatAdapter;
23 import jalview.io.IdentifyFile;
24 import jalview.io.JalviewFileChooser;
25 import jalview.io.JalviewFileView;
26 import jalview.ws.params.ParamManager;
28 import java.awt.BorderLayout;
29 import java.awt.Color;
30 import java.awt.Dimension;
31 import java.awt.FontMetrics;
32 import java.awt.Graphics;
33 import java.awt.GridLayout;
34 import java.awt.Point;
35 import java.awt.Rectangle;
36 import java.awt.Toolkit;
37 import java.awt.datatransfer.Clipboard;
38 import java.awt.datatransfer.ClipboardOwner;
39 import java.awt.datatransfer.DataFlavor;
40 import java.awt.datatransfer.Transferable;
41 import java.awt.dnd.DnDConstants;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetEvent;
45 import java.awt.dnd.DropTargetListener;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.awt.event.MouseAdapter;
51 import java.awt.event.MouseEvent;
52 import java.awt.event.MouseListener;
53 import java.awt.event.WindowAdapter;
54 import java.awt.event.WindowEvent;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.beans.PropertyVetoException;
58 import java.io.BufferedInputStream;
60 import java.io.FileOutputStream;
61 import java.lang.reflect.Constructor;
63 import java.util.ArrayList;
64 import java.util.Hashtable;
65 import java.util.StringTokenizer;
66 import java.util.Vector;
67 import java.util.concurrent.ExecutorService;
68 import java.util.concurrent.Executors;
70 import javax.swing.DefaultDesktopManager;
71 import javax.swing.DesktopManager;
72 import javax.swing.JButton;
73 import javax.swing.JComboBox;
74 import javax.swing.JComponent;
75 import javax.swing.JDesktopPane;
76 import javax.swing.JFrame;
77 import javax.swing.JInternalFrame;
78 import javax.swing.JLabel;
79 import javax.swing.JMenuItem;
80 import javax.swing.JOptionPane;
81 import javax.swing.JPanel;
82 import javax.swing.JPopupMenu;
83 import javax.swing.JProgressBar;
84 import javax.swing.SwingUtilities;
85 import javax.swing.event.HyperlinkEvent;
86 import javax.swing.event.MenuEvent;
87 import javax.swing.event.MenuListener;
88 import javax.swing.event.HyperlinkEvent.EventType;
95 * @version $Revision: 1.155 $
97 public class Desktop extends jalview.jbgui.GDesktop implements
98 DropTargetListener, ClipboardOwner, IProgressIndicator, jalview.api.StructureSelectionManagerProvider
101 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
104 * news reader - null if it was never started.
106 private BlogReader jvnews=null;
110 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
112 public void addJalviewPropertyChangeListener(
113 PropertyChangeListener listener)
115 changeSupport.addJalviewPropertyChangeListener(listener);
119 * @param propertyName
121 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
122 * java.beans.PropertyChangeListener)
124 public void addJalviewPropertyChangeListener(String propertyName,
125 PropertyChangeListener listener)
127 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
131 * @param propertyName
133 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
134 * java.beans.PropertyChangeListener)
136 public void removeJalviewPropertyChangeListener(String propertyName,
137 PropertyChangeListener listener)
139 changeSupport.removeJalviewPropertyChangeListener(propertyName,
143 /** Singleton Desktop instance */
144 public static Desktop instance;
146 public static MyDesktopPane desktop;
148 static int openFrameCount = 0;
150 static final int xOffset = 30;
152 static final int yOffset = 30;
154 public static jalview.ws.jws1.Discoverer discoverer;
156 public static Object[] jalviewClipboard;
158 public static boolean internalCopy = false;
160 static int fileLoadingCount = 0;
162 class MyDesktopManager implements DesktopManager
165 private DesktopManager delegate;
167 public MyDesktopManager(DesktopManager delegate)
169 this.delegate = delegate;
172 public void activateFrame(JInternalFrame f)
176 delegate.activateFrame(f);
177 } catch (NullPointerException npe)
179 Point p = getMousePosition();
180 instance.showPasteMenu(p.x, p.y);
184 public void beginDraggingFrame(JComponent f)
186 delegate.beginDraggingFrame(f);
189 public void beginResizingFrame(JComponent f, int direction)
191 delegate.beginResizingFrame(f, direction);
194 public void closeFrame(JInternalFrame f)
196 delegate.closeFrame(f);
199 public void deactivateFrame(JInternalFrame f)
201 delegate.deactivateFrame(f);
204 public void deiconifyFrame(JInternalFrame f)
206 delegate.deiconifyFrame(f);
209 public void dragFrame(JComponent f, int newX, int newY)
215 delegate.dragFrame(f, newX, newY);
218 public void endDraggingFrame(JComponent f)
220 delegate.endDraggingFrame(f);
223 public void endResizingFrame(JComponent f)
225 delegate.endResizingFrame(f);
228 public void iconifyFrame(JInternalFrame f)
230 delegate.iconifyFrame(f);
233 public void maximizeFrame(JInternalFrame f)
235 delegate.maximizeFrame(f);
238 public void minimizeFrame(JInternalFrame f)
240 delegate.minimizeFrame(f);
243 public void openFrame(JInternalFrame f)
245 delegate.openFrame(f);
248 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
251 Rectangle b=desktop.getBounds();
256 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
259 public void setBoundsForFrame(JComponent f, int newX, int newY,
260 int newWidth, int newHeight)
262 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
265 // All other methods, simply delegate
270 * Creates a new Desktop object.
275 * A note to implementors. It is ESSENTIAL that any activities that might
276 * block are spawned off as threads rather than waited for during this
280 doVamsasClientCheck();
283 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
284 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
285 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
287 boolean showjconsole = jalview.bin.Cache.getDefault(
288 "SHOW_JAVA_CONSOLE", false);
289 desktop = new MyDesktopPane(selmemusage);
290 showMemusage.setSelected(selmemusage);
291 desktop.setBackground(Color.white);
292 getContentPane().setLayout(new BorderLayout());
293 // alternate config - have scrollbars - see notes in JAL-153
294 //JScrollPane sp = new JScrollPane();
295 //sp.getViewport().setView(desktop);
296 //getContentPane().add(sp, BorderLayout.CENTER);
297 getContentPane().add(desktop, BorderLayout.CENTER);
298 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
301 // This line prevents Windows Look&Feel resizing all new windows to maximum
302 // if previous window was maximised
303 desktop.setDesktopManager(new MyDesktopManager(
304 new DefaultDesktopManager()));
306 Rectangle dims = getLastKnownDimensions("");
313 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
314 setBounds((int) (screenSize.width - 900) / 2,
315 (int) (screenSize.height - 650) / 2, 900, 650);
317 jconsole = new Console(this, showjconsole);
318 // add essential build information
319 jconsole.setHeader("Jalview Desktop "
320 + jalview.bin.Cache.getProperty("VERSION") + "\n"
322 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
323 + "Java version: " + System.getProperty("java.version") + "\n"
324 + System.getProperty("os.arch") + " "
325 + System.getProperty("os.name") + " "
326 + System.getProperty("os.version"));
328 showConsole(showjconsole);
330 showNews.setVisible(false);
331 final Desktop me = this;
332 // Thread off the news reader, in case there are connection problems.
333 new Thread( new Runnable() {
337 Cache.log.debug("Starting news thread.");
339 jvnews = new BlogReader(me);
340 showNews.setVisible(true);
341 Cache.log.debug("Completed news thread.");
345 this.addWindowListener(new WindowAdapter()
347 public void windowClosing(WindowEvent evt)
354 this.addMouseListener(ma=new MouseAdapter()
356 public void mousePressed(MouseEvent evt)
358 if (SwingUtilities.isRightMouseButton(evt))
360 showPasteMenu(evt.getX(), evt.getY());
364 desktop.addMouseListener(ma);
366 this.addFocusListener(new FocusListener()
370 public void focusLost(FocusEvent e)
372 // TODO Auto-generated method stub
377 public void focusGained(FocusEvent e)
379 Cache.log.debug("Relaying windows after focus gain");
380 // make sure that we sort windows properly after we gain focus
381 instance.relayerWindows();
384 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
385 // Spawn a thread that shows the splashscreen
386 SwingUtilities.invokeLater(new Runnable()
395 // Thread off a new instance of the file chooser - this reduces the time it
396 // takes to open it later on.
397 new Thread(new Runnable()
401 Cache.log.debug("Filechooser init thread started.");
402 JalviewFileChooser chooser = new JalviewFileChooser(
403 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
404 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
405 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
406 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
407 Cache.log.debug("Filechooser init thread finished.");
410 // Add the service change listener
411 changeSupport.addJalviewPropertyChangeListener("services",
412 new PropertyChangeListener()
416 public void propertyChange(PropertyChangeEvent evt)
418 Cache.log.debug("Firing service changed event for "
419 + evt.getNewValue());
420 JalviewServicesChanged(evt);
426 protected void showNews_actionPerformed(ActionEvent e)
428 showNews(showNews.isSelected());
430 void showNews(boolean visible)
433 Cache.log.debug((visible?"Showing":"Hiding")+" news.");
434 showNews.setSelected(visible);
435 if (visible && !jvnews.isVisible())
437 new Thread(new Runnable() {
441 long instance=System.currentTimeMillis();
442 Desktop.instance.setProgressBar("Refreshing news", instance);
443 jvnews.refreshNews();
444 Desktop.instance.setProgressBar(null, instance);
453 * recover the last known dimensions for a jalview window
456 * - empty string is desktop, all other windows have unique prefix
457 * @return null or last known dimensions scaled to current geometry (if last
458 * window geom was known)
460 Rectangle getLastKnownDimensions(String windowName)
462 // TODO: lock aspect ratio for scaling desktop Bug #0058199
463 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
464 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
465 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
466 String width = jalview.bin.Cache.getProperty(windowName
468 String height = jalview.bin.Cache.getProperty(windowName
470 if ((x != null) && (y != null) && (width != null) && (height != null))
472 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
473 .parseInt(width), ih = Integer.parseInt(height);
474 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
476 // attempt #1 - try to cope with change in screen geometry - this
477 // version doesn't preserve original jv aspect ratio.
478 // take ratio of current screen size vs original screen size.
479 double sw = ((1f * screenSize.width) / (1f * Integer
480 .parseInt(jalview.bin.Cache
481 .getProperty("SCREENGEOMETRY_WIDTH"))));
482 double sh = ((1f * screenSize.height) / (1f * Integer
483 .parseInt(jalview.bin.Cache
484 .getProperty("SCREENGEOMETRY_HEIGHT"))));
485 // rescale the bounds depending upon the current screen geometry.
486 ix = (int) (ix * sw);
487 iw = (int) (iw * sw);
488 iy = (int) (iy * sh);
489 ih = (int) (ih * sh);
490 while (ix >= screenSize.width)
492 jalview.bin.Cache.log
493 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
494 ix -= screenSize.width;
496 while (iy >= screenSize.height)
498 jalview.bin.Cache.log
499 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
500 iy -= screenSize.height;
502 jalview.bin.Cache.log.debug("Got last known dimensions for "
503 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
506 // return dimensions for new instance
507 return new Rectangle(ix, iy, iw, ih);
512 private void doVamsasClientCheck()
514 if (jalview.bin.Cache.vamsasJarsPresent())
516 setupVamsasDisconnectedGui();
517 VamsasMenu.setVisible(true);
518 final Desktop us = this;
519 VamsasMenu.addMenuListener(new MenuListener()
521 // this listener remembers when the menu was first selected, and
522 // doesn't rebuild the session list until it has been cleared and
524 boolean refresh = true;
526 public void menuCanceled(MenuEvent e)
531 public void menuDeselected(MenuEvent e)
536 public void menuSelected(MenuEvent e)
540 us.buildVamsasStMenu();
545 vamsasStart.setVisible(true);
549 void showPasteMenu(int x, int y)
551 JPopupMenu popup = new JPopupMenu();
552 JMenuItem item = new JMenuItem("Paste To New Window");
553 item.addActionListener(new ActionListener()
555 public void actionPerformed(ActionEvent evt)
562 popup.show(this, x, y);
569 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
570 Transferable contents = c.getContents(this);
572 if (contents != null)
574 String file = (String) contents
575 .getTransferData(DataFlavor.stringFlavor);
577 String format = new IdentifyFile().Identify(file,
578 FormatAdapter.PASTE);
580 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
583 } catch (Exception ex)
586 .println("Unable to paste alignment from system clipboard:\n"
592 * Adds and opens the given frame to the desktop
603 public static synchronized void addInternalFrame(
604 final JInternalFrame frame, String title, int w, int h)
606 addInternalFrame(frame, title, w, h, true);
623 public static synchronized void addInternalFrame(
624 final JInternalFrame frame, String title, int w, int h,
628 // TODO: allow callers to determine X and Y position of frame (eg. via
630 // TODO: consider fixing method to update entries in the window submenu with
631 // the current window title
633 frame.setTitle(title);
634 if (frame.getWidth() < 1 || frame.getHeight() < 1)
638 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
639 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
640 // IF JALVIEW IS RUNNING HEADLESS
641 // ///////////////////////////////////////////////
642 if (System.getProperty("java.awt.headless") != null
643 && System.getProperty("java.awt.headless").equals("true"))
650 frame.setVisible(true);
651 frame.setClosable(true);
652 frame.setResizable(resizable);
653 frame.setMaximizable(resizable);
654 frame.setIconifiable(resizable);
655 frame.setFrameIcon(null);
657 if (frame.getX() < 1 && frame.getY() < 1)
659 frame.setLocation(xOffset * openFrameCount, yOffset
660 * ((openFrameCount - 1) % 10) + yOffset);
663 final JMenuItem menuItem = new JMenuItem(title);
664 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
666 public void internalFrameActivated(
667 javax.swing.event.InternalFrameEvent evt)
669 JInternalFrame itf = desktop.getSelectedFrame();
677 public void internalFrameClosed(
678 javax.swing.event.InternalFrameEvent evt)
680 PaintRefresher.RemoveComponent(frame);
682 windowMenu.remove(menuItem);
683 JInternalFrame itf = desktop.getSelectedFrame();
692 menuItem.addActionListener(new ActionListener()
694 public void actionPerformed(ActionEvent e)
698 frame.setSelected(true);
699 frame.setIcon(false);
700 } catch (java.beans.PropertyVetoException ex)
706 menuItem.addMouseListener(new MouseListener()
710 public void mouseReleased(MouseEvent e)
715 public void mousePressed(MouseEvent e)
720 public void mouseExited(MouseEvent e)
724 frame.setSelected(false);
725 } catch (PropertyVetoException e1)
731 public void mouseEntered(MouseEvent e)
735 frame.setSelected(true);
736 } catch (PropertyVetoException e1)
742 public void mouseClicked(MouseEvent e)
748 windowMenu.add(menuItem);
754 frame.setSelected(true);
755 frame.requestFocus();
756 } catch (java.beans.PropertyVetoException ve)
759 catch (java.lang.ClassCastException cex)
761 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);
765 public void lostOwnership(Clipboard clipboard, Transferable contents)
769 Desktop.jalviewClipboard = null;
772 internalCopy = false;
775 public void dragEnter(DropTargetDragEvent evt)
779 public void dragExit(DropTargetEvent evt)
783 public void dragOver(DropTargetDragEvent evt)
787 public void dropActionChanged(DropTargetDragEvent evt)
797 public void drop(DropTargetDropEvent evt)
799 Transferable t = evt.getTransferable();
800 java.util.List files = null;
801 java.util.List protocols = null;
805 DataFlavor uriListFlavor = new DataFlavor(
806 "text/uri-list;class=java.lang.String");
807 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
809 // Works on Windows and MacOSX
810 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
811 files = (java.util.List) t
812 .getTransferData(DataFlavor.javaFileListFlavor);
814 else if (t.isDataFlavorSupported(uriListFlavor))
816 // This is used by Unix drag system
817 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
818 String data = (String) t.getTransferData(uriListFlavor);
819 files = new java.util.ArrayList(1);
820 protocols = new java.util.ArrayList(1);
821 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
822 data, "\r\n"); st.hasMoreTokens();)
824 String s = st.nextToken();
825 if (s.startsWith("#"))
827 // the line is a comment (as per the RFC 2483)
830 java.net.URI uri = new java.net.URI(s);
831 if (uri.getScheme().toLowerCase().startsWith("http"))
833 protocols.add(FormatAdapter.URL);
834 files.add(uri.toString());
838 // otherwise preserve old behaviour: catch all for file objects
839 java.io.File file = new java.io.File(uri);
840 protocols.add(FormatAdapter.FILE);
841 files.add(file.toString());
845 } catch (Exception e)
853 for (int i = 0; i < files.size(); i++)
855 String file = files.get(i).toString();
856 String protocol = (protocols == null) ? FormatAdapter.FILE
857 : (String) protocols.get(i);
858 String format = null;
860 if (file.endsWith(".jar"))
867 format = new IdentifyFile().Identify(file, protocol);
870 new FileLoader().LoadFile(file, protocol, format);
873 } catch (Exception ex)
885 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
887 JalviewFileChooser chooser = new JalviewFileChooser(
888 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
889 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
890 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
891 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
893 chooser.setFileView(new JalviewFileView());
894 chooser.setDialogTitle("Open local file");
895 chooser.setToolTipText("Open");
897 int value = chooser.showOpenDialog(this);
899 if (value == JalviewFileChooser.APPROVE_OPTION)
901 String choice = chooser.getSelectedFile().getPath();
902 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
903 .getSelectedFile().getParent());
905 String format = null;
906 if (chooser.getSelectedFormat().equals("Jalview"))
912 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
915 if (viewport != null)
917 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
922 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
933 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
935 // This construct allows us to have a wider textfield
937 JLabel label = new JLabel("Enter URL of Input File");
938 final JComboBox history = new JComboBox();
940 JPanel panel = new JPanel(new GridLayout(2, 1));
943 history.setPreferredSize(new Dimension(400, 20));
944 history.setEditable(true);
945 history.addItem("http://www.");
947 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
951 if (historyItems != null)
953 st = new StringTokenizer(historyItems, "\t");
955 while (st.hasMoreTokens())
957 history.addItem(st.nextElement());
961 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
962 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
964 if (reply != JOptionPane.OK_OPTION)
969 String url = history.getSelectedItem().toString();
971 if (url.toLowerCase().endsWith(".jar"))
973 if (viewport != null)
975 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
980 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
985 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
987 if (format.equals("URL NOT FOUND"))
989 JOptionPane.showInternalMessageDialog(Desktop.desktop,
990 "Couldn't locate " + url, "URL not found",
991 JOptionPane.WARNING_MESSAGE);
996 if (viewport != null)
998 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1002 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1013 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1015 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1016 cap.setForInput(viewport);
1017 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1025 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1027 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1028 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1030 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1031 getBounds().y, getWidth(), getHeight()));
1033 if (jconsole != null)
1035 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1036 jconsole.stopConsole();
1040 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1043 if (dialogExecutor!=null)
1045 dialogExecutor.shutdownNow();
1051 private void storeLastKnownDimensions(String string, Rectangle jc)
1053 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1054 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1055 + " height:" + jc.height);
1057 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1058 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1059 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1060 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1069 public void aboutMenuItem_actionPerformed(ActionEvent e)
1071 // StringBuffer message = getAboutMessage(false);
1072 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1074 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1075 new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
1078 public StringBuffer getAboutMessage(boolean shortv)
1080 StringBuffer message = new StringBuffer();
1081 message.append("<html>");
1084 message.append("<h1><strong>Version: "
1085 + jalview.bin.Cache.getProperty("VERSION")
1086 + "</strong></h1><br>");
1087 message.append("<strong>Last Updated: <em>"
1088 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1089 + "</em></strong>");
1095 message.append("<strong>Version "
1096 + jalview.bin.Cache.getProperty("VERSION")
1097 + "; last updated: "
1098 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1101 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1104 message.append("<br>...Checking latest version...</br>");
1106 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1107 .equals(jalview.bin.Cache.getProperty("VERSION")))
1109 boolean red = false;
1110 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1111 .indexOf("automated build") == -1)
1114 // Displayed when code version and jnlp version do not match and code
1115 // version is not a development build
1116 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1119 message.append("<br>!! Version "
1120 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1122 + " is available for download from "
1123 + jalview.bin.Cache.getDefault("www.jalview.org",
1124 "http://www.jalview.org") + " !!");
1127 message.append("</div>");
1130 message.append("<br>Authors: "
1134 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1135 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1136 + "<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"
1137 + "<br>If you use Jalview, please cite:"
1138 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1139 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1140 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1151 public void documentationMenuItem_actionPerformed(ActionEvent e)
1155 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1156 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1157 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1159 javax.help.HelpBroker hb = hs.createHelpBroker();
1160 hb.setCurrentID("home");
1161 hb.setDisplayed(true);
1162 } catch (Exception ex)
1167 public void closeAll_actionPerformed(ActionEvent e)
1169 JInternalFrame[] frames = desktop.getAllFrames();
1170 for (int i = 0; i < frames.length; i++)
1174 frames[i].setClosed(true);
1175 } catch (java.beans.PropertyVetoException ex)
1179 System.out.println("ALL CLOSED");
1180 if (v_client != null)
1182 // TODO clear binding to vamsas document objects on close_all
1187 public void raiseRelated_actionPerformed(ActionEvent e)
1189 reorderAssociatedWindows(false, false);
1192 public void minimizeAssociated_actionPerformed(ActionEvent e)
1194 reorderAssociatedWindows(true, false);
1197 void closeAssociatedWindows()
1199 reorderAssociatedWindows(false, true);
1205 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1208 protected void garbageCollect_actionPerformed(ActionEvent e)
1210 // We simply collect the garbage
1211 jalview.bin.Cache.log.debug("Collecting garbage...");
1213 jalview.bin.Cache.log.debug("Finished garbage collection.");
1220 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1223 protected void showMemusage_actionPerformed(ActionEvent e)
1225 desktop.showMemoryUsage(showMemusage.isSelected());
1232 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1235 protected void showConsole_actionPerformed(ActionEvent e)
1237 showConsole(showConsole.isSelected());
1240 Console jconsole = null;
1243 * control whether the java console is visible or not
1247 void showConsole(boolean selected)
1249 showConsole.setSelected(selected);
1250 // TODO: decide if we should update properties file
1251 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1253 jconsole.setVisible(selected);
1256 void reorderAssociatedWindows(boolean minimize, boolean close)
1258 JInternalFrame[] frames = desktop.getAllFrames();
1259 if (frames == null || frames.length < 1)
1264 AlignViewport source = null, target = null;
1265 if (frames[0] instanceof AlignFrame)
1267 source = ((AlignFrame) frames[0]).getCurrentView();
1269 else if (frames[0] instanceof TreePanel)
1271 source = ((TreePanel) frames[0]).getViewPort();
1273 else if (frames[0] instanceof PCAPanel)
1275 source = ((PCAPanel) frames[0]).av;
1277 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1279 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1284 for (int i = 0; i < frames.length; i++)
1287 if (frames[i] == null)
1291 if (frames[i] instanceof AlignFrame)
1293 target = ((AlignFrame) frames[i]).getCurrentView();
1295 else if (frames[i] instanceof TreePanel)
1297 target = ((TreePanel) frames[i]).getViewPort();
1299 else if (frames[i] instanceof PCAPanel)
1301 target = ((PCAPanel) frames[i]).av;
1303 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1305 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1308 if (source == target)
1314 frames[i].setClosed(true);
1318 frames[i].setIcon(minimize);
1321 frames[i].toFront();
1325 } catch (java.beans.PropertyVetoException ex)
1339 protected void preferences_actionPerformed(ActionEvent e)
1350 public void saveState_actionPerformed(ActionEvent e)
1352 JalviewFileChooser chooser = new JalviewFileChooser(
1353 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1354 { "jar" }, new String[]
1355 { "Jalview Project" }, "Jalview Project");
1357 chooser.setFileView(new JalviewFileView());
1358 chooser.setDialogTitle("Save State");
1360 int value = chooser.showSaveDialog(this);
1362 if (value == JalviewFileChooser.APPROVE_OPTION)
1364 final Desktop me = this;
1365 final java.io.File choice = chooser.getSelectedFile();
1366 new Thread(new Runnable()
1371 setProgressBar("Saving jalview project " + choice.getName(),
1373 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1374 // TODO catch and handle errors for savestate
1375 // TODO prevent user from messing with the Desktop whilst we're saving
1378 new Jalview2XML().SaveState(choice);
1379 } catch (OutOfMemoryError oom)
1382 "Whilst saving current state to " + choice.getName(), oom);
1383 } catch (Exception ex)
1386 .error("Problems whilst trying to save to "
1387 + choice.getName(), ex);
1388 JOptionPane.showMessageDialog(me,
1389 "Error whilst saving current state to " + choice.getName(),
1390 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1392 setProgressBar(null, choice.hashCode());
1404 public void loadState_actionPerformed(ActionEvent e)
1406 JalviewFileChooser chooser = new JalviewFileChooser(
1407 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1408 { "jar" }, new String[]
1409 { "Jalview Project" }, "Jalview Project");
1410 chooser.setFileView(new JalviewFileView());
1411 chooser.setDialogTitle("Restore state");
1413 int value = chooser.showOpenDialog(this);
1415 if (value == JalviewFileChooser.APPROVE_OPTION)
1417 final String choice = chooser.getSelectedFile().getAbsolutePath();
1418 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1419 .getSelectedFile().getParent());
1420 new Thread(new Runnable()
1424 setProgressBar("loading jalview project " + choice,
1428 new Jalview2XML().LoadJalviewAlign(choice);
1429 } catch (OutOfMemoryError oom)
1431 new OOMWarning("Whilst loading project from " + choice, oom);
1432 } catch (Exception ex)
1434 Cache.log.error("Problems whilst loading project from "
1436 JOptionPane.showMessageDialog(Desktop.desktop,
1437 "Error whilst loading project from " + choice,
1438 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1440 setProgressBar(null, choice.hashCode());
1446 public void inputSequence_actionPerformed(ActionEvent e)
1448 new SequenceFetcher(this);
1451 JPanel progressPanel;
1452 ArrayList<JPanel> fileLoadingPanels=new ArrayList<JPanel>();
1453 public void startLoading(final String fileName)
1455 if (fileLoadingCount == 0)
1457 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName + " "));
1462 private JPanel addProgressPanel(String string)
1464 if (progressPanel == null)
1466 progressPanel = new JPanel(new GridLayout(1,1));
1467 totalProgressCount = 0;
1468 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1470 JPanel thisprogress=new JPanel(new BorderLayout(10,5));
1471 JProgressBar progressBar = new JProgressBar();
1472 progressBar.setIndeterminate(true);
1474 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1476 thisprogress.add(progressBar, BorderLayout.CENTER);
1477 progressPanel.add(thisprogress);
1478 ((GridLayout)progressPanel.getLayout()).setRows(((GridLayout)progressPanel.getLayout()).getRows()+1);
1479 ++totalProgressCount;
1480 instance.validate();
1481 return thisprogress;
1484 int totalProgressCount = 0;
1486 private void removeProgressPanel(JPanel progbar)
1488 if (progressPanel != null)
1490 progressPanel.remove(progbar);
1491 GridLayout gl = (GridLayout) progressPanel.getLayout();
1492 gl.setRows(gl.getRows()-1);
1493 if (--totalProgressCount < 1)
1495 this.getContentPane().remove(progressPanel);
1496 progressPanel = null;
1502 public void stopLoading()
1505 if (fileLoadingCount < 1)
1507 for (JPanel flp : fileLoadingPanels)
1509 removeProgressPanel(flp);
1511 fileLoadingPanels.clear();
1512 fileLoadingCount = 0;
1517 public static int getViewCount(String alignmentId)
1519 AlignViewport[] aps = getViewports(alignmentId);
1520 return (aps == null) ? 0 : aps.length;
1525 * @param alignmentId
1526 * @return all AlignmentPanels concerning the alignmentId sequence set
1528 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1531 if (Desktop.desktop == null)
1533 // no frames created and in headless mode
1534 // TODO: verify that frames are recoverable when in headless mode
1537 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1538 ArrayList aps = new ArrayList();
1539 for (int t = 0; t < frames.length; t++)
1541 if (frames[t] instanceof AlignFrame)
1543 AlignFrame af = (AlignFrame) frames[t];
1544 for (int a = 0; a < af.alignPanels.size(); a++)
1547 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1548 .getSequenceSetId()))
1550 aps.add(af.alignPanels.elementAt(a));
1555 if (aps.size() == 0)
1559 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1560 for (int t = 0; t < vap.length; t++)
1562 vap[t] = (AlignmentPanel) aps.get(t);
1568 * get all the viewports on an alignment.
1570 * @param sequenceSetId
1571 * unique alignment id
1572 * @return all viewports on the alignment bound to sequenceSetId
1574 public static AlignViewport[] getViewports(String sequenceSetId)
1576 Vector viewp = new Vector();
1577 if (desktop != null)
1579 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1581 for (int t = 0; t < frames.length; t++)
1583 if (frames[t] instanceof AlignFrame)
1585 AlignFrame afr = ((AlignFrame) frames[t]);
1586 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1588 if (afr.alignPanels != null)
1590 for (int a = 0; a < afr.alignPanels.size(); a++)
1592 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1593 .elementAt(a)).av.getSequenceSetId()))
1595 viewp.addElement(((AlignmentPanel) afr.alignPanels
1602 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1607 if (viewp.size() > 0)
1609 AlignViewport[] vp = new AlignViewport[viewp.size()];
1617 public void explodeViews(AlignFrame af)
1619 int size = af.alignPanels.size();
1625 for (int i = 0; i < size; i++)
1627 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1628 AlignFrame newaf = new AlignFrame(ap);
1629 if (ap.av.explodedPosition != null
1630 && !ap.av.explodedPosition.equals(af.getBounds()))
1632 newaf.setBounds(ap.av.explodedPosition);
1635 ap.av.gatherViewsHere = false;
1637 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1638 AlignFrame.DEFAULT_HEIGHT);
1641 af.alignPanels.clear();
1642 af.closeMenuItem_actionPerformed(true);
1646 public void gatherViews(AlignFrame source)
1648 source.viewport.gatherViewsHere = true;
1649 source.viewport.explodedPosition = source.getBounds();
1650 JInternalFrame[] frames = desktop.getAllFrames();
1651 String viewId = source.viewport.getSequenceSetId();
1653 for (int t = 0; t < frames.length; t++)
1655 if (frames[t] instanceof AlignFrame && frames[t] != source)
1657 AlignFrame af = (AlignFrame) frames[t];
1658 boolean gatherThis = false;
1659 for (int a = 0; a < af.alignPanels.size(); a++)
1661 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1662 if (viewId.equals(ap.av.getSequenceSetId()))
1665 ap.av.gatherViewsHere = false;
1666 ap.av.explodedPosition = af.getBounds();
1667 source.addAlignmentPanel(ap, false);
1673 af.alignPanels.clear();
1674 af.closeMenuItem_actionPerformed(true);
1681 jalview.gui.VamsasApplication v_client = null;
1683 public void vamsasImport_actionPerformed(ActionEvent e)
1685 if (v_client == null)
1687 // Load and try to start a session.
1688 JalviewFileChooser chooser = new JalviewFileChooser(
1689 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1691 chooser.setFileView(new JalviewFileView());
1692 chooser.setDialogTitle("Open a saved VAMSAS session");
1693 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1695 int value = chooser.showOpenDialog(this);
1697 if (value == JalviewFileChooser.APPROVE_OPTION)
1699 String fle = chooser.getSelectedFile().toString();
1700 if (!vamsasImport(chooser.getSelectedFile()))
1702 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1703 "Couldn't import '" + fle + "' as a new vamsas session.",
1704 "Vamsas Document Import Failed",
1705 JOptionPane.ERROR_MESSAGE);
1711 jalview.bin.Cache.log
1712 .error("Implementation error - load session from a running session is not supported.");
1717 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1720 * @return true if import was a success and a session was started.
1722 public boolean vamsasImport(URL url)
1724 // TODO: create progress bar
1725 if (v_client != null)
1728 jalview.bin.Cache.log
1729 .error("Implementation error - load session from a running session is not supported.");
1735 // copy the URL content to a temporary local file
1736 // TODO: be a bit cleverer here with nio (?!)
1737 File file = File.createTempFile("vdocfromurl", ".vdj");
1738 FileOutputStream fos = new FileOutputStream(file);
1739 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1740 byte[] buffer = new byte[2048];
1742 while ((ln = bis.read(buffer)) > -1)
1744 fos.write(buffer, 0, ln);
1748 v_client = new jalview.gui.VamsasApplication(this, file,
1749 url.toExternalForm());
1750 } catch (Exception ex)
1752 jalview.bin.Cache.log.error(
1753 "Failed to create new vamsas session from contents of URL "
1757 setupVamsasConnectedGui();
1758 v_client.initial_update(); // TODO: thread ?
1759 return v_client.inSession();
1763 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1766 * @return true if import was a success and a session was started.
1768 public boolean vamsasImport(File file)
1770 if (v_client != null)
1773 jalview.bin.Cache.log
1774 .error("Implementation error - load session from a running session is not supported.");
1778 setProgressBar("Importing VAMSAS session from " + file.getName(),
1782 v_client = new jalview.gui.VamsasApplication(this, file, null);
1783 } catch (Exception ex)
1785 setProgressBar("Importing VAMSAS session from " + file.getName(),
1787 jalview.bin.Cache.log.error(
1788 "New vamsas session from existing session file failed:", ex);
1791 setupVamsasConnectedGui();
1792 v_client.initial_update(); // TODO: thread ?
1793 setProgressBar("Importing VAMSAS session from " + file.getName(),
1795 return v_client.inSession();
1798 public boolean joinVamsasSession(String mysesid)
1800 if (v_client != null)
1803 "Trying to join a vamsas session when another is already connected.");
1805 if (mysesid == null)
1807 throw new Error("Invalid vamsas session id.");
1809 v_client = new VamsasApplication(this, mysesid);
1810 setupVamsasConnectedGui();
1811 v_client.initial_update();
1812 return (v_client.inSession());
1815 public void vamsasStart_actionPerformed(ActionEvent e)
1817 if (v_client == null)
1820 // we just start a default session for moment.
1822 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1823 * getProperty("LAST_DIRECTORY"));
1825 * chooser.setFileView(new JalviewFileView());
1826 * chooser.setDialogTitle("Load Vamsas file");
1827 * chooser.setToolTipText("Import");
1829 * int value = chooser.showOpenDialog(this);
1831 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1832 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1834 v_client = new VamsasApplication(this);
1835 setupVamsasConnectedGui();
1836 v_client.initial_update(); // TODO: thread ?
1840 // store current data in session.
1841 v_client.push_update(); // TODO: thread
1845 protected void setupVamsasConnectedGui()
1847 vamsasStart.setText("Session Update");
1848 vamsasSave.setVisible(true);
1849 vamsasStop.setVisible(true);
1850 vamsasImport.setVisible(false); // Document import to existing session is
1851 // not possible for vamsas-client-1.0.
1854 protected void setupVamsasDisconnectedGui()
1856 vamsasSave.setVisible(false);
1857 vamsasStop.setVisible(false);
1858 vamsasImport.setVisible(true);
1859 vamsasStart.setText("New Vamsas Session");
1862 public void vamsasStop_actionPerformed(ActionEvent e)
1864 if (v_client != null)
1866 v_client.end_session();
1868 setupVamsasDisconnectedGui();
1872 protected void buildVamsasStMenu()
1874 if (v_client == null)
1876 String[] sess = null;
1879 sess = VamsasApplication.getSessionList();
1880 } catch (Exception e)
1882 jalview.bin.Cache.log.warn(
1883 "Problem getting current sessions list.", e);
1888 jalview.bin.Cache.log.debug("Got current sessions list: "
1889 + sess.length + " entries.");
1890 VamsasStMenu.removeAll();
1891 for (int i = 0; i < sess.length; i++)
1893 JMenuItem sessit = new JMenuItem();
1894 sessit.setText(sess[i]);
1895 sessit.setToolTipText("Connect to session " + sess[i]);
1896 final Desktop dsktp = this;
1897 final String mysesid = sess[i];
1898 sessit.addActionListener(new ActionListener()
1901 public void actionPerformed(ActionEvent e)
1903 if (dsktp.v_client == null)
1905 Thread rthr = new Thread(new Runnable()
1910 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1911 dsktp.setupVamsasConnectedGui();
1912 dsktp.v_client.initial_update();
1920 VamsasStMenu.add(sessit);
1922 // don't show an empty menu.
1923 VamsasStMenu.setVisible(sess.length > 0);
1928 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1929 VamsasStMenu.removeAll();
1930 VamsasStMenu.setVisible(false);
1935 // Not interested in the content. Just hide ourselves.
1936 VamsasStMenu.setVisible(false);
1940 public void vamsasSave_actionPerformed(ActionEvent e)
1942 if (v_client != null)
1944 JalviewFileChooser chooser = new JalviewFileChooser(
1945 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1946 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1948 { "Vamsas Document" }, "Vamsas Document");
1950 chooser.setFileView(new JalviewFileView());
1951 chooser.setDialogTitle("Save Vamsas Document Archive");
1953 int value = chooser.showSaveDialog(this);
1955 if (value == JalviewFileChooser.APPROVE_OPTION)
1957 java.io.File choice = chooser.getSelectedFile();
1958 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1959 + choice.getName());
1960 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1961 String warnmsg = null;
1962 String warnttl = null;
1965 v_client.vclient.storeDocument(choice);
1968 warnttl = "Serious Problem saving Vamsas Document";
1969 warnmsg = ex.toString();
1970 jalview.bin.Cache.log.error("Error Whilst saving document to "
1973 } catch (Exception ex)
1975 warnttl = "Problem saving Vamsas Document.";
1976 warnmsg = ex.toString();
1977 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1981 removeProgressPanel(progpanel);
1982 if (warnmsg != null)
1984 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1986 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1992 JPanel vamUpdate = null;
1995 * hide vamsas user gui bits when a vamsas document event is being handled.
1998 * true to hide gui, false to reveal gui
2000 public void setVamsasUpdate(boolean b)
2002 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2003 + (b ? "in progress" : "finished"));
2005 if (vamUpdate != null)
2007 this.removeProgressPanel(vamUpdate);
2011 vamUpdate = this.addProgressPanel("Updating vamsas session");
2013 vamsasStart.setVisible(!b);
2014 vamsasStop.setVisible(!b);
2015 vamsasSave.setVisible(!b);
2018 public JInternalFrame[] getAllFrames()
2020 return desktop.getAllFrames();
2024 * Checks the given url to see if it gives a response indicating that the user
2025 * should be informed of a new questionnaire.
2029 public void checkForQuestionnaire(String url)
2031 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2032 // javax.swing.SwingUtilities.invokeLater(jvq);
2033 new Thread(jvq).start();
2037 * Proxy class for JDesktopPane which optionally displays the current memory
2038 * usage and highlights the desktop area with a red bar if free memory runs
2043 public class MyDesktopPane extends JDesktopPane implements Runnable
2046 boolean showMemoryUsage = false;
2050 java.text.NumberFormat df;
2052 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2055 public MyDesktopPane(boolean showMemoryUsage)
2057 showMemoryUsage(showMemoryUsage);
2060 public void showMemoryUsage(boolean showMemoryUsage)
2062 this.showMemoryUsage = showMemoryUsage;
2063 if (showMemoryUsage)
2065 Thread worker = new Thread(this);
2070 public boolean isShowMemoryUsage()
2072 return showMemoryUsage;
2077 df = java.text.NumberFormat.getNumberInstance();
2078 df.setMaximumFractionDigits(2);
2079 runtime = Runtime.getRuntime();
2081 while (showMemoryUsage)
2085 maxMemory = runtime.maxMemory() / 1048576f;
2086 allocatedMemory = runtime.totalMemory() / 1048576f;
2087 freeMemory = runtime.freeMemory() / 1048576f;
2088 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2090 percentUsage = (totalFreeMemory / maxMemory) * 100;
2092 // if (percentUsage < 20)
2094 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2096 // instance.set.setBorder(border1);
2099 // sleep after showing usage
2101 } catch (Exception ex)
2103 ex.printStackTrace();
2108 public void paintComponent(Graphics g)
2110 if (showMemoryUsage && g != null && df != null)
2112 if (percentUsage < 20)
2113 g.setColor(Color.red);
2114 FontMetrics fm = g.getFontMetrics();
2118 "Total Free Memory: " + df.format(totalFreeMemory)
2119 + "MB; Max Memory: " + df.format(maxMemory)
2120 + "MB; " + df.format(percentUsage) + "%", 10,
2121 getHeight() - fm.getHeight());
2128 * fixes stacking order after a modal dialog to ensure windows that should be on top actually are
2130 public void relayerWindows()
2135 protected JMenuItem groovyShell;
2137 public void doGroovyCheck()
2139 if (jalview.bin.Cache.groovyJarsPresent())
2141 groovyShell = new JMenuItem();
2142 groovyShell.setText("Groovy Console...");
2143 groovyShell.addActionListener(new ActionListener()
2145 public void actionPerformed(ActionEvent e)
2147 groovyShell_actionPerformed(e);
2150 toolsMenu.add(groovyShell);
2151 groovyShell.setVisible(true);
2156 * Accessor method to quickly get all the AlignmentFrames loaded.
2158 public static AlignFrame[] getAlignframes()
2160 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2166 Vector avp = new Vector();
2170 for (int i = frames.length - 1; i > -1; i--)
2172 if (frames[i] instanceof AlignFrame)
2174 AlignFrame af = (AlignFrame) frames[i];
2178 } catch (Exception ex)
2180 ex.printStackTrace();
2182 if (avp.size() == 0)
2186 AlignFrame afs[] = new AlignFrame[avp.size()];
2187 for (int i = 0, j = avp.size(); i < j; i++)
2189 afs[i] = (AlignFrame) avp.elementAt(i);
2194 public AppJmol[] getJmols()
2196 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2202 Vector avp = new Vector();
2206 for (int i = frames.length - 1; i > -1; i--)
2208 if (frames[i] instanceof AppJmol)
2210 AppJmol af = (AppJmol) frames[i];
2214 } catch (Exception ex)
2216 ex.printStackTrace();
2218 if (avp.size() == 0)
2222 AppJmol afs[] = new AppJmol[avp.size()];
2223 for (int i = 0, j = avp.size(); i < j; i++)
2225 afs[i] = (AppJmol) avp.elementAt(i);
2232 * Add Groovy Support to Jalview
2234 public void groovyShell_actionPerformed(ActionEvent e)
2236 // use reflection to avoid creating compilation dependency.
2237 if (!jalview.bin.Cache.groovyJarsPresent())
2240 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2244 Class gcClass = Desktop.class.getClassLoader().loadClass(
2245 "groovy.ui.Console");
2246 Constructor gccons = gcClass.getConstructor(null);
2247 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2249 { String.class, Object.class });
2250 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2251 Object gc = gccons.newInstance(null);
2252 setvar.invoke(gc, new Object[]
2253 { "Jalview", this });
2254 run.invoke(gc, null);
2255 } catch (Exception ex)
2257 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2259 .showInternalMessageDialog(
2262 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2263 "Jalview Groovy Support Failed",
2264 JOptionPane.ERROR_MESSAGE);
2269 * Progress bars managed by the IProgressIndicator method.
2271 private Hashtable<Long,JPanel> progressBars;
2272 private Hashtable<Long,IProgressIndicatorHandler> progressBarHandlers;
2277 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2279 public void setProgressBar(String message, long id)
2281 if (progressBars == null)
2283 progressBars = new Hashtable<Long,JPanel>();
2284 progressBarHandlers = new Hashtable<Long,IProgressIndicatorHandler>();
2287 if (progressBars.get(new Long(id)) != null)
2289 JPanel progressPanel = progressBars
2290 .remove(new Long(id));
2291 if (progressBarHandlers.contains(new Long(id)))
2293 progressBarHandlers.remove(new Long(id));
2295 removeProgressPanel(progressPanel);
2299 progressBars.put(new Long(id), addProgressPanel(message));
2306 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2307 * jalview.gui.IProgressIndicatorHandler)
2309 public void registerHandler(final long id,
2310 final IProgressIndicatorHandler handler)
2312 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2315 "call setProgressBar before registering the progress bar's handler.");
2317 progressBarHandlers.put(new Long(id), handler);
2318 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2319 if (handler.canCancel())
2321 JButton cancel = new JButton("Cancel");
2322 final IProgressIndicator us = this;
2323 cancel.addActionListener(new ActionListener()
2326 public void actionPerformed(ActionEvent e)
2328 handler.cancelActivity(id);
2331 + ((JLabel) progressPanel.getComponent(0))
2335 progressPanel.add(cancel, BorderLayout.EAST);
2341 * @return true if any progress bars are still active
2344 public boolean operationInProgress()
2346 if (progressBars != null && progressBars.size() > 0)
2354 * This will return the first AlignFrame viewing AlignViewport av. It will
2355 * break if there are more than one AlignFrames viewing a particular av. This
2358 * @return alignFrame for av
2360 public static AlignFrame getAlignFrameFor(AlignViewport av)
2362 if (desktop != null)
2364 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2365 for (int panel = 0; aps != null && panel < aps.length; panel++)
2367 if (aps[panel] != null && aps[panel].av == av)
2369 return aps[panel].alignFrame;
2376 public VamsasApplication getVamsasApplication()
2383 * flag set if jalview GUI is being operated programmatically
2385 private boolean inBatchMode = false;
2388 * check if jalview GUI is being operated programmatically
2390 * @return inBatchMode
2392 public boolean isInBatchMode()
2398 * set flag if jalview GUI is being operated programmatically
2400 * @param inBatchMode
2402 public void setInBatchMode(boolean inBatchMode)
2404 this.inBatchMode = inBatchMode;
2407 public void startServiceDiscovery()
2409 startServiceDiscovery(false);
2412 public void startServiceDiscovery(boolean blocking)
2414 boolean alive = true;
2415 Thread t0 = null, t1 = null, t2 = null;
2417 // todo: changesupport handlers need to be transferred
2418 if (discoverer == null)
2420 discoverer = new jalview.ws.jws1.Discoverer();
2421 // register PCS handler for desktop.
2422 discoverer.addPropertyChangeListener(changeSupport);
2424 // JAL-940 - disabled JWS1 service configuration - always start discoverer until we phase out completely
2427 (t0 = new Thread(discoverer)).start();
2432 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2434 // EnfinEnvision web service menu entries are rebuild every time the
2435 // menu is shown, so no changeSupport events are needed.
2436 jalview.ws.EnfinEnvision2OneWay.getInstance();
2437 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2440 } catch (Exception e)
2443 .info("Exception when trying to launch Envision2 workflow discovery.",
2445 Cache.log.info(e.getStackTrace());
2447 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2449 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2451 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2453 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2459 // TODO: do rest service discovery
2468 } catch (Exception e)
2471 alive = (t1 != null && t1.isAlive())
2472 || (t2 != null && t2.isAlive())
2473 || (t3 != null && t3.isAlive())
2474 || (t0 != null && t0.isAlive());
2480 * called to check if the service discovery process completed successfully.
2484 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2486 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2488 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2489 .getErrorMessages();
2492 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2494 if (serviceChangedDialog == null)
2496 // only run if we aren't already displaying one of these.
2497 javax.swing.SwingUtilities
2498 .invokeLater(serviceChangedDialog = new Runnable()
2504 .showInternalMessageDialog(
2507 + "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",
2508 "Preferences Problem",
2509 JOptionPane.WARNING_MESSAGE);
2510 serviceChangedDialog = null;
2519 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2526 private Runnable serviceChangedDialog = null;
2529 * start a thread to open a URL in the configured browser. Pops up a warning
2530 * dialog to the user if there is an exception when calling out to the browser
2535 public static void showUrl(final String url)
2537 showUrl(url, Desktop.instance);
2540 * Like showUrl but allows progress handler to be specified
2542 * @param progress (null) or object implementing IProgressIndicator
2544 public static void showUrl(final String url, final IProgressIndicator progress)
2546 new Thread(new Runnable()
2552 if (progress!=null) {
2553 progress.setProgressBar("Opening "+url, this.hashCode());
2555 jalview.util.BrowserLauncher.openURL(url);
2556 } catch (Exception ex)
2559 .showInternalMessageDialog(
2561 "Unixers: Couldn't find default web browser."
2562 + "\nAdd the full path to your browser in Preferences.",
2563 "Web browser not found",
2564 JOptionPane.WARNING_MESSAGE);
2566 ex.printStackTrace();
2568 if (progress!=null) {
2569 progress.setProgressBar(null, this.hashCode());
2575 public static WsParamSetManager wsparamManager = null;
2577 public static ParamManager getUserParameterStore()
2579 if (wsparamManager == null)
2581 wsparamManager = new WsParamSetManager();
2583 return wsparamManager;
2587 * static hyperlink handler proxy method for use by Jalview's internal windows
2590 public static void hyperlinkUpdate(HyperlinkEvent e)
2592 if (e.getEventType() == EventType.ACTIVATED)
2597 url = e.getURL().toString();
2598 Desktop.showUrl(url);
2599 } catch (Exception x)
2602 if (Cache.log!=null) {
2603 Cache.log.error("Couldn't handle string "+url+" as a URL.");
2605 System.err.println("Couldn't handle string "+url+" as a URL.");
2608 // ignore any exceptions due to dud links.
2614 * single thread that handles display of dialogs to user.
2616 ExecutorService dialogExecutor=null;
2619 * add another dialog thread to the queue
2622 public synchronized void addDialogThread(Runnable prompter)
2624 if (dialogExecutor==null)
2626 dialogExecutor = Executors.newSingleThreadExecutor();
2628 dialogExecutor.submit(prompter);