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;
70 import java.util.concurrent.Semaphore;
72 import javax.swing.DefaultDesktopManager;
73 import javax.swing.DesktopManager;
74 import javax.swing.JButton;
75 import javax.swing.JComboBox;
76 import javax.swing.JComponent;
77 import javax.swing.JDesktopPane;
78 import javax.swing.JFrame;
79 import javax.swing.JInternalFrame;
80 import javax.swing.JLabel;
81 import javax.swing.JMenuItem;
82 import javax.swing.JOptionPane;
83 import javax.swing.JPanel;
84 import javax.swing.JPopupMenu;
85 import javax.swing.JProgressBar;
86 import javax.swing.SwingUtilities;
87 import javax.swing.event.HyperlinkEvent;
88 import javax.swing.event.MenuEvent;
89 import javax.swing.event.MenuListener;
90 import javax.swing.event.HyperlinkEvent.EventType;
97 * @version $Revision: 1.155 $
99 public class Desktop extends jalview.jbgui.GDesktop implements
100 DropTargetListener, ClipboardOwner, IProgressIndicator, jalview.api.StructureSelectionManagerProvider
103 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
106 * news reader - null if it was never started.
108 private BlogReader jvnews=null;
112 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
114 public void addJalviewPropertyChangeListener(
115 PropertyChangeListener listener)
117 changeSupport.addJalviewPropertyChangeListener(listener);
121 * @param propertyName
123 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
124 * java.beans.PropertyChangeListener)
126 public void addJalviewPropertyChangeListener(String propertyName,
127 PropertyChangeListener listener)
129 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
133 * @param propertyName
135 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
136 * java.beans.PropertyChangeListener)
138 public void removeJalviewPropertyChangeListener(String propertyName,
139 PropertyChangeListener listener)
141 changeSupport.removeJalviewPropertyChangeListener(propertyName,
145 /** Singleton Desktop instance */
146 public static Desktop instance;
148 public static MyDesktopPane desktop;
150 static int openFrameCount = 0;
152 static final int xOffset = 30;
154 static final int yOffset = 30;
156 public static jalview.ws.jws1.Discoverer discoverer;
158 public static Object[] jalviewClipboard;
160 public static boolean internalCopy = false;
162 static int fileLoadingCount = 0;
164 class MyDesktopManager implements DesktopManager
167 private DesktopManager delegate;
169 public MyDesktopManager(DesktopManager delegate)
171 this.delegate = delegate;
174 public void activateFrame(JInternalFrame f)
178 delegate.activateFrame(f);
179 } catch (NullPointerException npe)
181 Point p = getMousePosition();
182 instance.showPasteMenu(p.x, p.y);
186 public void beginDraggingFrame(JComponent f)
188 delegate.beginDraggingFrame(f);
191 public void beginResizingFrame(JComponent f, int direction)
193 delegate.beginResizingFrame(f, direction);
196 public void closeFrame(JInternalFrame f)
198 delegate.closeFrame(f);
201 public void deactivateFrame(JInternalFrame f)
203 delegate.deactivateFrame(f);
206 public void deiconifyFrame(JInternalFrame f)
208 delegate.deiconifyFrame(f);
211 public void dragFrame(JComponent f, int newX, int newY)
217 delegate.dragFrame(f, newX, newY);
220 public void endDraggingFrame(JComponent f)
222 delegate.endDraggingFrame(f);
225 public void endResizingFrame(JComponent f)
227 delegate.endResizingFrame(f);
230 public void iconifyFrame(JInternalFrame f)
232 delegate.iconifyFrame(f);
235 public void maximizeFrame(JInternalFrame f)
237 delegate.maximizeFrame(f);
240 public void minimizeFrame(JInternalFrame f)
242 delegate.minimizeFrame(f);
245 public void openFrame(JInternalFrame f)
247 delegate.openFrame(f);
250 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
253 Rectangle b=desktop.getBounds();
258 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
261 public void setBoundsForFrame(JComponent f, int newX, int newY,
262 int newWidth, int newHeight)
264 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
267 // All other methods, simply delegate
272 * Creates a new Desktop object.
277 * A note to implementors. It is ESSENTIAL that any activities that might
278 * block are spawned off as threads rather than waited for during this
282 doVamsasClientCheck();
285 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
286 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
287 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
289 boolean showjconsole = jalview.bin.Cache.getDefault(
290 "SHOW_JAVA_CONSOLE", false);
291 desktop = new MyDesktopPane(selmemusage);
292 showMemusage.setSelected(selmemusage);
293 desktop.setBackground(Color.white);
294 getContentPane().setLayout(new BorderLayout());
295 // alternate config - have scrollbars - see notes in JAL-153
296 //JScrollPane sp = new JScrollPane();
297 //sp.getViewport().setView(desktop);
298 //getContentPane().add(sp, BorderLayout.CENTER);
299 getContentPane().add(desktop, BorderLayout.CENTER);
300 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
303 // This line prevents Windows Look&Feel resizing all new windows to maximum
304 // if previous window was maximised
305 desktop.setDesktopManager(new MyDesktopManager(
306 new DefaultDesktopManager()));
308 Rectangle dims = getLastKnownDimensions("");
315 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
316 setBounds((int) (screenSize.width - 900) / 2,
317 (int) (screenSize.height - 650) / 2, 900, 650);
319 jconsole = new Console(this, showjconsole);
320 // add essential build information
321 jconsole.setHeader("Jalview Desktop "
322 + jalview.bin.Cache.getProperty("VERSION") + "\n"
324 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
325 + "Java version: " + System.getProperty("java.version") + "\n"
326 + System.getProperty("os.arch") + " "
327 + System.getProperty("os.name") + " "
328 + System.getProperty("os.version"));
330 showConsole(showjconsole);
332 showNews.setVisible(false);
334 this.addWindowListener(new WindowAdapter()
336 public void windowClosing(WindowEvent evt)
343 this.addMouseListener(ma=new MouseAdapter()
345 public void mousePressed(MouseEvent evt)
347 if (SwingUtilities.isRightMouseButton(evt))
349 showPasteMenu(evt.getX(), evt.getY());
353 desktop.addMouseListener(ma);
355 this.addFocusListener(new FocusListener()
359 public void focusLost(FocusEvent e)
361 // TODO Auto-generated method stub
366 public void focusGained(FocusEvent e)
368 Cache.log.debug("Relaying windows after focus gain");
369 // make sure that we sort windows properly after we gain focus
370 instance.relayerWindows();
373 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
374 // Spawn a thread that shows the splashscreen
375 SwingUtilities.invokeLater(new Runnable()
384 // Thread off a new instance of the file chooser - this reduces the time it
385 // takes to open it later on.
386 new Thread(new Runnable()
390 Cache.log.debug("Filechooser init thread started.");
391 JalviewFileChooser chooser = new JalviewFileChooser(
392 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
393 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
394 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
395 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
396 Cache.log.debug("Filechooser init thread finished.");
399 // Add the service change listener
400 changeSupport.addJalviewPropertyChangeListener("services",
401 new PropertyChangeListener()
405 public void propertyChange(PropertyChangeEvent evt)
407 Cache.log.debug("Firing service changed event for "
408 + evt.getNewValue());
409 JalviewServicesChanged(evt);
415 public void checkForNews()
417 final Desktop me = this;
418 // Thread off the news reader, in case there are connection problems.
419 addDialogThread(new Runnable() {
423 Cache.log.debug("Starting news thread.");
425 jvnews = new BlogReader(me);
426 showNews.setVisible(true);
427 Cache.log.debug("Completed news thread.");
431 protected void showNews_actionPerformed(ActionEvent e)
433 showNews(showNews.isSelected());
435 void showNews(boolean visible)
438 Cache.log.debug((visible?"Showing":"Hiding")+" news.");
439 showNews.setSelected(visible);
440 if (visible && !jvnews.isVisible())
442 new Thread(new Runnable() {
446 long instance=System.currentTimeMillis();
447 Desktop.instance.setProgressBar("Refreshing news", instance);
448 jvnews.refreshNews();
449 Desktop.instance.setProgressBar(null, instance);
458 * recover the last known dimensions for a jalview window
461 * - empty string is desktop, all other windows have unique prefix
462 * @return null or last known dimensions scaled to current geometry (if last
463 * window geom was known)
465 Rectangle getLastKnownDimensions(String windowName)
467 // TODO: lock aspect ratio for scaling desktop Bug #0058199
468 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
469 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
470 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
471 String width = jalview.bin.Cache.getProperty(windowName
473 String height = jalview.bin.Cache.getProperty(windowName
475 if ((x != null) && (y != null) && (width != null) && (height != null))
477 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
478 .parseInt(width), ih = Integer.parseInt(height);
479 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
481 // attempt #1 - try to cope with change in screen geometry - this
482 // version doesn't preserve original jv aspect ratio.
483 // take ratio of current screen size vs original screen size.
484 double sw = ((1f * screenSize.width) / (1f * Integer
485 .parseInt(jalview.bin.Cache
486 .getProperty("SCREENGEOMETRY_WIDTH"))));
487 double sh = ((1f * screenSize.height) / (1f * Integer
488 .parseInt(jalview.bin.Cache
489 .getProperty("SCREENGEOMETRY_HEIGHT"))));
490 // rescale the bounds depending upon the current screen geometry.
491 ix = (int) (ix * sw);
492 iw = (int) (iw * sw);
493 iy = (int) (iy * sh);
494 ih = (int) (ih * sh);
495 while (ix >= screenSize.width)
497 jalview.bin.Cache.log
498 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
499 ix -= screenSize.width;
501 while (iy >= screenSize.height)
503 jalview.bin.Cache.log
504 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
505 iy -= screenSize.height;
507 jalview.bin.Cache.log.debug("Got last known dimensions for "
508 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
511 // return dimensions for new instance
512 return new Rectangle(ix, iy, iw, ih);
517 private void doVamsasClientCheck()
519 if (jalview.bin.Cache.vamsasJarsPresent())
521 setupVamsasDisconnectedGui();
522 VamsasMenu.setVisible(true);
523 final Desktop us = this;
524 VamsasMenu.addMenuListener(new MenuListener()
526 // this listener remembers when the menu was first selected, and
527 // doesn't rebuild the session list until it has been cleared and
529 boolean refresh = true;
531 public void menuCanceled(MenuEvent e)
536 public void menuDeselected(MenuEvent e)
541 public void menuSelected(MenuEvent e)
545 us.buildVamsasStMenu();
550 vamsasStart.setVisible(true);
554 void showPasteMenu(int x, int y)
556 JPopupMenu popup = new JPopupMenu();
557 JMenuItem item = new JMenuItem("Paste To New Window");
558 item.addActionListener(new ActionListener()
560 public void actionPerformed(ActionEvent evt)
567 popup.show(this, x, y);
574 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
575 Transferable contents = c.getContents(this);
577 if (contents != null)
579 String file = (String) contents
580 .getTransferData(DataFlavor.stringFlavor);
582 String format = new IdentifyFile().Identify(file,
583 FormatAdapter.PASTE);
585 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
588 } catch (Exception ex)
591 .println("Unable to paste alignment from system clipboard:\n"
597 * Adds and opens the given frame to the desktop
608 public static synchronized void addInternalFrame(
609 final JInternalFrame frame, String title, int w, int h)
611 addInternalFrame(frame, title, w, h, true);
628 public static synchronized void addInternalFrame(
629 final JInternalFrame frame, String title, int w, int h,
633 // TODO: allow callers to determine X and Y position of frame (eg. via
635 // TODO: consider fixing method to update entries in the window submenu with
636 // the current window title
638 frame.setTitle(title);
639 if (frame.getWidth() < 1 || frame.getHeight() < 1)
643 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
644 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
645 // IF JALVIEW IS RUNNING HEADLESS
646 // ///////////////////////////////////////////////
647 if (System.getProperty("java.awt.headless") != null
648 && System.getProperty("java.awt.headless").equals("true"))
655 frame.setVisible(true);
656 frame.setClosable(true);
657 frame.setResizable(resizable);
658 frame.setMaximizable(resizable);
659 frame.setIconifiable(resizable);
660 frame.setFrameIcon(null);
662 if (frame.getX() < 1 && frame.getY() < 1)
664 frame.setLocation(xOffset * openFrameCount, yOffset
665 * ((openFrameCount - 1) % 10) + yOffset);
668 final JMenuItem menuItem = new JMenuItem(title);
669 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
671 public void internalFrameActivated(
672 javax.swing.event.InternalFrameEvent evt)
674 JInternalFrame itf = desktop.getSelectedFrame();
682 public void internalFrameClosed(
683 javax.swing.event.InternalFrameEvent evt)
685 PaintRefresher.RemoveComponent(frame);
687 windowMenu.remove(menuItem);
688 JInternalFrame itf = desktop.getSelectedFrame();
697 menuItem.addActionListener(new ActionListener()
699 public void actionPerformed(ActionEvent e)
703 frame.setSelected(true);
704 frame.setIcon(false);
705 } catch (java.beans.PropertyVetoException ex)
711 menuItem.addMouseListener(new MouseListener()
715 public void mouseReleased(MouseEvent e)
720 public void mousePressed(MouseEvent e)
725 public void mouseExited(MouseEvent e)
729 frame.setSelected(false);
730 } catch (PropertyVetoException e1)
736 public void mouseEntered(MouseEvent e)
740 frame.setSelected(true);
741 } catch (PropertyVetoException e1)
747 public void mouseClicked(MouseEvent e)
753 windowMenu.add(menuItem);
759 frame.setSelected(true);
760 frame.requestFocus();
761 } catch (java.beans.PropertyVetoException ve)
764 catch (java.lang.ClassCastException cex)
766 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);
770 public void lostOwnership(Clipboard clipboard, Transferable contents)
774 Desktop.jalviewClipboard = null;
777 internalCopy = false;
780 public void dragEnter(DropTargetDragEvent evt)
784 public void dragExit(DropTargetEvent evt)
788 public void dragOver(DropTargetDragEvent evt)
792 public void dropActionChanged(DropTargetDragEvent evt)
802 public void drop(DropTargetDropEvent evt)
804 Transferable t = evt.getTransferable();
805 java.util.List files = null;
806 java.util.List protocols = null;
810 DataFlavor uriListFlavor = new DataFlavor(
811 "text/uri-list;class=java.lang.String");
812 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
814 // Works on Windows and MacOSX
815 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
816 files = (java.util.List) t
817 .getTransferData(DataFlavor.javaFileListFlavor);
819 else if (t.isDataFlavorSupported(uriListFlavor))
821 // This is used by Unix drag system
822 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
823 String data = (String) t.getTransferData(uriListFlavor);
824 files = new java.util.ArrayList(1);
825 protocols = new java.util.ArrayList(1);
826 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
827 data, "\r\n"); st.hasMoreTokens();)
829 String s = st.nextToken();
830 if (s.startsWith("#"))
832 // the line is a comment (as per the RFC 2483)
835 java.net.URI uri = new java.net.URI(s);
836 if (uri.getScheme().toLowerCase().startsWith("http"))
838 protocols.add(FormatAdapter.URL);
839 files.add(uri.toString());
843 // otherwise preserve old behaviour: catch all for file objects
844 java.io.File file = new java.io.File(uri);
845 protocols.add(FormatAdapter.FILE);
846 files.add(file.toString());
850 } catch (Exception e)
858 for (int i = 0; i < files.size(); i++)
860 String file = files.get(i).toString();
861 String protocol = (protocols == null) ? FormatAdapter.FILE
862 : (String) protocols.get(i);
863 String format = null;
865 if (file.endsWith(".jar"))
872 format = new IdentifyFile().Identify(file, protocol);
875 new FileLoader().LoadFile(file, protocol, format);
878 } catch (Exception ex)
890 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
892 JalviewFileChooser chooser = new JalviewFileChooser(
893 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
894 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
895 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
896 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
898 chooser.setFileView(new JalviewFileView());
899 chooser.setDialogTitle("Open local file");
900 chooser.setToolTipText("Open");
902 int value = chooser.showOpenDialog(this);
904 if (value == JalviewFileChooser.APPROVE_OPTION)
906 String choice = chooser.getSelectedFile().getPath();
907 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
908 .getSelectedFile().getParent());
910 String format = null;
911 if (chooser.getSelectedFormat().equals("Jalview"))
917 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
920 if (viewport != null)
922 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
927 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
938 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
940 // This construct allows us to have a wider textfield
942 JLabel label = new JLabel("Enter URL of Input File");
943 final JComboBox history = new JComboBox();
945 JPanel panel = new JPanel(new GridLayout(2, 1));
948 history.setPreferredSize(new Dimension(400, 20));
949 history.setEditable(true);
950 history.addItem("http://www.");
952 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
956 if (historyItems != null)
958 st = new StringTokenizer(historyItems, "\t");
960 while (st.hasMoreTokens())
962 history.addItem(st.nextElement());
966 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
967 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
969 if (reply != JOptionPane.OK_OPTION)
974 String url = history.getSelectedItem().toString();
976 if (url.toLowerCase().endsWith(".jar"))
978 if (viewport != null)
980 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
985 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
990 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
992 if (format.equals("URL NOT FOUND"))
994 JOptionPane.showInternalMessageDialog(Desktop.desktop,
995 "Couldn't locate " + url, "URL not found",
996 JOptionPane.WARNING_MESSAGE);
1001 if (viewport != null)
1003 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1007 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1018 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1020 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1021 cap.setForInput(viewport);
1022 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1030 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1032 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1033 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1035 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1036 getBounds().y, getWidth(), getHeight()));
1038 if (jconsole != null)
1040 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1041 jconsole.stopConsole();
1045 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1048 if (dialogExecutor!=null)
1050 dialogExecutor.shutdownNow();
1056 private void storeLastKnownDimensions(String string, Rectangle jc)
1058 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1059 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1060 + " height:" + jc.height);
1062 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1063 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1064 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1065 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1074 public void aboutMenuItem_actionPerformed(ActionEvent e)
1076 // StringBuffer message = getAboutMessage(false);
1077 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1079 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1080 new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
1083 public StringBuffer getAboutMessage(boolean shortv)
1085 StringBuffer message = new StringBuffer();
1086 message.append("<html>");
1089 message.append("<h1><strong>Version: "
1090 + jalview.bin.Cache.getProperty("VERSION")
1091 + "</strong></h1><br>");
1092 message.append("<strong>Last Updated: <em>"
1093 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1094 + "</em></strong>");
1100 message.append("<strong>Version "
1101 + jalview.bin.Cache.getProperty("VERSION")
1102 + "; last updated: "
1103 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1106 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1109 message.append("<br>...Checking latest version...</br>");
1111 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1112 .equals(jalview.bin.Cache.getProperty("VERSION")))
1114 boolean red = false;
1115 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1116 .indexOf("automated build") == -1)
1119 // Displayed when code version and jnlp version do not match and code
1120 // version is not a development build
1121 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1124 message.append("<br>!! Version "
1125 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1127 + " is available for download from "
1128 + jalview.bin.Cache.getDefault("www.jalview.org",
1129 "http://www.jalview.org") + " !!");
1132 message.append("</div>");
1135 message.append("<br>Authors: "
1139 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1140 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1141 + "<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"
1142 + "<br>If you use Jalview, please cite:"
1143 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1144 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1145 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1156 public void documentationMenuItem_actionPerformed(ActionEvent e)
1160 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1161 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1162 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1164 javax.help.HelpBroker hb = hs.createHelpBroker();
1165 hb.setCurrentID("home");
1166 hb.setDisplayed(true);
1167 } catch (Exception ex)
1172 public void closeAll_actionPerformed(ActionEvent e)
1174 JInternalFrame[] frames = desktop.getAllFrames();
1175 for (int i = 0; i < frames.length; i++)
1179 frames[i].setClosed(true);
1180 } catch (java.beans.PropertyVetoException ex)
1184 System.out.println("ALL CLOSED");
1185 if (v_client != null)
1187 // TODO clear binding to vamsas document objects on close_all
1192 public void raiseRelated_actionPerformed(ActionEvent e)
1194 reorderAssociatedWindows(false, false);
1197 public void minimizeAssociated_actionPerformed(ActionEvent e)
1199 reorderAssociatedWindows(true, false);
1202 void closeAssociatedWindows()
1204 reorderAssociatedWindows(false, true);
1210 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1213 protected void garbageCollect_actionPerformed(ActionEvent e)
1215 // We simply collect the garbage
1216 jalview.bin.Cache.log.debug("Collecting garbage...");
1218 jalview.bin.Cache.log.debug("Finished garbage collection.");
1225 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1228 protected void showMemusage_actionPerformed(ActionEvent e)
1230 desktop.showMemoryUsage(showMemusage.isSelected());
1237 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1240 protected void showConsole_actionPerformed(ActionEvent e)
1242 showConsole(showConsole.isSelected());
1245 Console jconsole = null;
1248 * control whether the java console is visible or not
1252 void showConsole(boolean selected)
1254 showConsole.setSelected(selected);
1255 // TODO: decide if we should update properties file
1256 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1258 jconsole.setVisible(selected);
1261 void reorderAssociatedWindows(boolean minimize, boolean close)
1263 JInternalFrame[] frames = desktop.getAllFrames();
1264 if (frames == null || frames.length < 1)
1269 AlignViewport source = null, target = null;
1270 if (frames[0] instanceof AlignFrame)
1272 source = ((AlignFrame) frames[0]).getCurrentView();
1274 else if (frames[0] instanceof TreePanel)
1276 source = ((TreePanel) frames[0]).getViewPort();
1278 else if (frames[0] instanceof PCAPanel)
1280 source = ((PCAPanel) frames[0]).av;
1282 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1284 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1289 for (int i = 0; i < frames.length; i++)
1292 if (frames[i] == null)
1296 if (frames[i] instanceof AlignFrame)
1298 target = ((AlignFrame) frames[i]).getCurrentView();
1300 else if (frames[i] instanceof TreePanel)
1302 target = ((TreePanel) frames[i]).getViewPort();
1304 else if (frames[i] instanceof PCAPanel)
1306 target = ((PCAPanel) frames[i]).av;
1308 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1310 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1313 if (source == target)
1319 frames[i].setClosed(true);
1323 frames[i].setIcon(minimize);
1326 frames[i].toFront();
1330 } catch (java.beans.PropertyVetoException ex)
1344 protected void preferences_actionPerformed(ActionEvent e)
1355 public void saveState_actionPerformed(ActionEvent e)
1357 JalviewFileChooser chooser = new JalviewFileChooser(
1358 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1359 { "jar" }, new String[]
1360 { "Jalview Project" }, "Jalview Project");
1362 chooser.setFileView(new JalviewFileView());
1363 chooser.setDialogTitle("Save State");
1365 int value = chooser.showSaveDialog(this);
1367 if (value == JalviewFileChooser.APPROVE_OPTION)
1369 final Desktop me = this;
1370 final java.io.File choice = chooser.getSelectedFile();
1371 new Thread(new Runnable()
1376 setProgressBar("Saving jalview project " + choice.getName(),
1378 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1379 // TODO catch and handle errors for savestate
1380 // TODO prevent user from messing with the Desktop whilst we're saving
1383 new Jalview2XML().SaveState(choice);
1384 } catch (OutOfMemoryError oom)
1387 "Whilst saving current state to " + choice.getName(), oom);
1388 } catch (Exception ex)
1391 .error("Problems whilst trying to save to "
1392 + choice.getName(), ex);
1393 JOptionPane.showMessageDialog(me,
1394 "Error whilst saving current state to " + choice.getName(),
1395 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1397 setProgressBar(null, choice.hashCode());
1409 public void loadState_actionPerformed(ActionEvent e)
1411 JalviewFileChooser chooser = new JalviewFileChooser(
1412 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1413 { "jar" }, new String[]
1414 { "Jalview Project" }, "Jalview Project");
1415 chooser.setFileView(new JalviewFileView());
1416 chooser.setDialogTitle("Restore state");
1418 int value = chooser.showOpenDialog(this);
1420 if (value == JalviewFileChooser.APPROVE_OPTION)
1422 final String choice = chooser.getSelectedFile().getAbsolutePath();
1423 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1424 .getSelectedFile().getParent());
1425 new Thread(new Runnable()
1429 setProgressBar("loading jalview project " + choice,
1433 new Jalview2XML().LoadJalviewAlign(choice);
1434 } catch (OutOfMemoryError oom)
1436 new OOMWarning("Whilst loading project from " + choice, oom);
1437 } catch (Exception ex)
1439 Cache.log.error("Problems whilst loading project from "
1441 JOptionPane.showMessageDialog(Desktop.desktop,
1442 "Error whilst loading project from " + choice,
1443 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1445 setProgressBar(null, choice.hashCode());
1451 public void inputSequence_actionPerformed(ActionEvent e)
1453 new SequenceFetcher(this);
1456 JPanel progressPanel;
1457 ArrayList<JPanel> fileLoadingPanels=new ArrayList<JPanel>();
1458 public void startLoading(final String fileName)
1460 if (fileLoadingCount == 0)
1462 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName + " "));
1467 private JPanel addProgressPanel(String string)
1469 if (progressPanel == null)
1471 progressPanel = new JPanel(new GridLayout(1,1));
1472 totalProgressCount = 0;
1473 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1475 JPanel thisprogress=new JPanel(new BorderLayout(10,5));
1476 JProgressBar progressBar = new JProgressBar();
1477 progressBar.setIndeterminate(true);
1479 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1481 thisprogress.add(progressBar, BorderLayout.CENTER);
1482 progressPanel.add(thisprogress);
1483 ((GridLayout)progressPanel.getLayout()).setRows(((GridLayout)progressPanel.getLayout()).getRows()+1);
1484 ++totalProgressCount;
1485 instance.validate();
1486 return thisprogress;
1489 int totalProgressCount = 0;
1491 private void removeProgressPanel(JPanel progbar)
1493 if (progressPanel != null)
1495 progressPanel.remove(progbar);
1496 GridLayout gl = (GridLayout) progressPanel.getLayout();
1497 gl.setRows(gl.getRows()-1);
1498 if (--totalProgressCount < 1)
1500 this.getContentPane().remove(progressPanel);
1501 progressPanel = null;
1507 public void stopLoading()
1510 if (fileLoadingCount < 1)
1512 for (JPanel flp : fileLoadingPanels)
1514 removeProgressPanel(flp);
1516 fileLoadingPanels.clear();
1517 fileLoadingCount = 0;
1522 public static int getViewCount(String alignmentId)
1524 AlignViewport[] aps = getViewports(alignmentId);
1525 return (aps == null) ? 0 : aps.length;
1530 * @param alignmentId
1531 * @return all AlignmentPanels concerning the alignmentId sequence set
1533 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1536 if (Desktop.desktop == null)
1538 // no frames created and in headless mode
1539 // TODO: verify that frames are recoverable when in headless mode
1542 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1543 ArrayList aps = new ArrayList();
1544 for (int t = 0; t < frames.length; t++)
1546 if (frames[t] instanceof AlignFrame)
1548 AlignFrame af = (AlignFrame) frames[t];
1549 for (int a = 0; a < af.alignPanels.size(); a++)
1552 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1553 .getSequenceSetId()))
1555 aps.add(af.alignPanels.elementAt(a));
1560 if (aps.size() == 0)
1564 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1565 for (int t = 0; t < vap.length; t++)
1567 vap[t] = (AlignmentPanel) aps.get(t);
1573 * get all the viewports on an alignment.
1575 * @param sequenceSetId
1576 * unique alignment id
1577 * @return all viewports on the alignment bound to sequenceSetId
1579 public static AlignViewport[] getViewports(String sequenceSetId)
1581 Vector viewp = new Vector();
1582 if (desktop != null)
1584 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1586 for (int t = 0; t < frames.length; t++)
1588 if (frames[t] instanceof AlignFrame)
1590 AlignFrame afr = ((AlignFrame) frames[t]);
1591 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1593 if (afr.alignPanels != null)
1595 for (int a = 0; a < afr.alignPanels.size(); a++)
1597 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1598 .elementAt(a)).av.getSequenceSetId()))
1600 viewp.addElement(((AlignmentPanel) afr.alignPanels
1607 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1612 if (viewp.size() > 0)
1614 AlignViewport[] vp = new AlignViewport[viewp.size()];
1622 public void explodeViews(AlignFrame af)
1624 int size = af.alignPanels.size();
1630 for (int i = 0; i < size; i++)
1632 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1633 AlignFrame newaf = new AlignFrame(ap);
1634 if (ap.av.explodedPosition != null
1635 && !ap.av.explodedPosition.equals(af.getBounds()))
1637 newaf.setBounds(ap.av.explodedPosition);
1640 ap.av.gatherViewsHere = false;
1642 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1643 AlignFrame.DEFAULT_HEIGHT);
1646 af.alignPanels.clear();
1647 af.closeMenuItem_actionPerformed(true);
1651 public void gatherViews(AlignFrame source)
1653 source.viewport.gatherViewsHere = true;
1654 source.viewport.explodedPosition = source.getBounds();
1655 JInternalFrame[] frames = desktop.getAllFrames();
1656 String viewId = source.viewport.getSequenceSetId();
1658 for (int t = 0; t < frames.length; t++)
1660 if (frames[t] instanceof AlignFrame && frames[t] != source)
1662 AlignFrame af = (AlignFrame) frames[t];
1663 boolean gatherThis = false;
1664 for (int a = 0; a < af.alignPanels.size(); a++)
1666 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1667 if (viewId.equals(ap.av.getSequenceSetId()))
1670 ap.av.gatherViewsHere = false;
1671 ap.av.explodedPosition = af.getBounds();
1672 source.addAlignmentPanel(ap, false);
1678 af.alignPanels.clear();
1679 af.closeMenuItem_actionPerformed(true);
1686 jalview.gui.VamsasApplication v_client = null;
1688 public void vamsasImport_actionPerformed(ActionEvent e)
1690 if (v_client == null)
1692 // Load and try to start a session.
1693 JalviewFileChooser chooser = new JalviewFileChooser(
1694 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1696 chooser.setFileView(new JalviewFileView());
1697 chooser.setDialogTitle("Open a saved VAMSAS session");
1698 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1700 int value = chooser.showOpenDialog(this);
1702 if (value == JalviewFileChooser.APPROVE_OPTION)
1704 String fle = chooser.getSelectedFile().toString();
1705 if (!vamsasImport(chooser.getSelectedFile()))
1707 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1708 "Couldn't import '" + fle + "' as a new vamsas session.",
1709 "Vamsas Document Import Failed",
1710 JOptionPane.ERROR_MESSAGE);
1716 jalview.bin.Cache.log
1717 .error("Implementation error - load session from a running session is not supported.");
1722 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1725 * @return true if import was a success and a session was started.
1727 public boolean vamsasImport(URL url)
1729 // TODO: create progress bar
1730 if (v_client != null)
1733 jalview.bin.Cache.log
1734 .error("Implementation error - load session from a running session is not supported.");
1740 // copy the URL content to a temporary local file
1741 // TODO: be a bit cleverer here with nio (?!)
1742 File file = File.createTempFile("vdocfromurl", ".vdj");
1743 FileOutputStream fos = new FileOutputStream(file);
1744 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1745 byte[] buffer = new byte[2048];
1747 while ((ln = bis.read(buffer)) > -1)
1749 fos.write(buffer, 0, ln);
1753 v_client = new jalview.gui.VamsasApplication(this, file,
1754 url.toExternalForm());
1755 } catch (Exception ex)
1757 jalview.bin.Cache.log.error(
1758 "Failed to create new vamsas session from contents of URL "
1762 setupVamsasConnectedGui();
1763 v_client.initial_update(); // TODO: thread ?
1764 return v_client.inSession();
1768 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1771 * @return true if import was a success and a session was started.
1773 public boolean vamsasImport(File file)
1775 if (v_client != null)
1778 jalview.bin.Cache.log
1779 .error("Implementation error - load session from a running session is not supported.");
1783 setProgressBar("Importing VAMSAS session from " + file.getName(),
1787 v_client = new jalview.gui.VamsasApplication(this, file, null);
1788 } catch (Exception ex)
1790 setProgressBar("Importing VAMSAS session from " + file.getName(),
1792 jalview.bin.Cache.log.error(
1793 "New vamsas session from existing session file failed:", ex);
1796 setupVamsasConnectedGui();
1797 v_client.initial_update(); // TODO: thread ?
1798 setProgressBar("Importing VAMSAS session from " + file.getName(),
1800 return v_client.inSession();
1803 public boolean joinVamsasSession(String mysesid)
1805 if (v_client != null)
1808 "Trying to join a vamsas session when another is already connected.");
1810 if (mysesid == null)
1812 throw new Error("Invalid vamsas session id.");
1814 v_client = new VamsasApplication(this, mysesid);
1815 setupVamsasConnectedGui();
1816 v_client.initial_update();
1817 return (v_client.inSession());
1820 public void vamsasStart_actionPerformed(ActionEvent e)
1822 if (v_client == null)
1825 // we just start a default session for moment.
1827 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1828 * getProperty("LAST_DIRECTORY"));
1830 * chooser.setFileView(new JalviewFileView());
1831 * chooser.setDialogTitle("Load Vamsas file");
1832 * chooser.setToolTipText("Import");
1834 * int value = chooser.showOpenDialog(this);
1836 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1837 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1839 v_client = new VamsasApplication(this);
1840 setupVamsasConnectedGui();
1841 v_client.initial_update(); // TODO: thread ?
1845 // store current data in session.
1846 v_client.push_update(); // TODO: thread
1850 protected void setupVamsasConnectedGui()
1852 vamsasStart.setText("Session Update");
1853 vamsasSave.setVisible(true);
1854 vamsasStop.setVisible(true);
1855 vamsasImport.setVisible(false); // Document import to existing session is
1856 // not possible for vamsas-client-1.0.
1859 protected void setupVamsasDisconnectedGui()
1861 vamsasSave.setVisible(false);
1862 vamsasStop.setVisible(false);
1863 vamsasImport.setVisible(true);
1864 vamsasStart.setText("New Vamsas Session");
1867 public void vamsasStop_actionPerformed(ActionEvent e)
1869 if (v_client != null)
1871 v_client.end_session();
1873 setupVamsasDisconnectedGui();
1877 protected void buildVamsasStMenu()
1879 if (v_client == null)
1881 String[] sess = null;
1884 sess = VamsasApplication.getSessionList();
1885 } catch (Exception e)
1887 jalview.bin.Cache.log.warn(
1888 "Problem getting current sessions list.", e);
1893 jalview.bin.Cache.log.debug("Got current sessions list: "
1894 + sess.length + " entries.");
1895 VamsasStMenu.removeAll();
1896 for (int i = 0; i < sess.length; i++)
1898 JMenuItem sessit = new JMenuItem();
1899 sessit.setText(sess[i]);
1900 sessit.setToolTipText("Connect to session " + sess[i]);
1901 final Desktop dsktp = this;
1902 final String mysesid = sess[i];
1903 sessit.addActionListener(new ActionListener()
1906 public void actionPerformed(ActionEvent e)
1908 if (dsktp.v_client == null)
1910 Thread rthr = new Thread(new Runnable()
1915 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1916 dsktp.setupVamsasConnectedGui();
1917 dsktp.v_client.initial_update();
1925 VamsasStMenu.add(sessit);
1927 // don't show an empty menu.
1928 VamsasStMenu.setVisible(sess.length > 0);
1933 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1934 VamsasStMenu.removeAll();
1935 VamsasStMenu.setVisible(false);
1940 // Not interested in the content. Just hide ourselves.
1941 VamsasStMenu.setVisible(false);
1945 public void vamsasSave_actionPerformed(ActionEvent e)
1947 if (v_client != null)
1949 JalviewFileChooser chooser = new JalviewFileChooser(
1950 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1951 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1953 { "Vamsas Document" }, "Vamsas Document");
1955 chooser.setFileView(new JalviewFileView());
1956 chooser.setDialogTitle("Save Vamsas Document Archive");
1958 int value = chooser.showSaveDialog(this);
1960 if (value == JalviewFileChooser.APPROVE_OPTION)
1962 java.io.File choice = chooser.getSelectedFile();
1963 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1964 + choice.getName());
1965 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1966 String warnmsg = null;
1967 String warnttl = null;
1970 v_client.vclient.storeDocument(choice);
1973 warnttl = "Serious Problem saving Vamsas Document";
1974 warnmsg = ex.toString();
1975 jalview.bin.Cache.log.error("Error Whilst saving document to "
1978 } catch (Exception ex)
1980 warnttl = "Problem saving Vamsas Document.";
1981 warnmsg = ex.toString();
1982 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1986 removeProgressPanel(progpanel);
1987 if (warnmsg != null)
1989 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1991 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1997 JPanel vamUpdate = null;
2000 * hide vamsas user gui bits when a vamsas document event is being handled.
2003 * true to hide gui, false to reveal gui
2005 public void setVamsasUpdate(boolean b)
2007 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2008 + (b ? "in progress" : "finished"));
2010 if (vamUpdate != null)
2012 this.removeProgressPanel(vamUpdate);
2016 vamUpdate = this.addProgressPanel("Updating vamsas session");
2018 vamsasStart.setVisible(!b);
2019 vamsasStop.setVisible(!b);
2020 vamsasSave.setVisible(!b);
2023 public JInternalFrame[] getAllFrames()
2025 return desktop.getAllFrames();
2029 * Checks the given url to see if it gives a response indicating that the user
2030 * should be informed of a new questionnaire.
2034 public void checkForQuestionnaire(String url)
2036 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2037 // javax.swing.SwingUtilities.invokeLater(jvq);
2038 new Thread(jvq).start();
2042 * Proxy class for JDesktopPane which optionally displays the current memory
2043 * usage and highlights the desktop area with a red bar if free memory runs
2048 public class MyDesktopPane extends JDesktopPane implements Runnable
2051 boolean showMemoryUsage = false;
2055 java.text.NumberFormat df;
2057 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2060 public MyDesktopPane(boolean showMemoryUsage)
2062 showMemoryUsage(showMemoryUsage);
2065 public void showMemoryUsage(boolean showMemoryUsage)
2067 this.showMemoryUsage = showMemoryUsage;
2068 if (showMemoryUsage)
2070 Thread worker = new Thread(this);
2075 public boolean isShowMemoryUsage()
2077 return showMemoryUsage;
2082 df = java.text.NumberFormat.getNumberInstance();
2083 df.setMaximumFractionDigits(2);
2084 runtime = Runtime.getRuntime();
2086 while (showMemoryUsage)
2090 maxMemory = runtime.maxMemory() / 1048576f;
2091 allocatedMemory = runtime.totalMemory() / 1048576f;
2092 freeMemory = runtime.freeMemory() / 1048576f;
2093 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2095 percentUsage = (totalFreeMemory / maxMemory) * 100;
2097 // if (percentUsage < 20)
2099 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2101 // instance.set.setBorder(border1);
2104 // sleep after showing usage
2106 } catch (Exception ex)
2108 ex.printStackTrace();
2113 public void paintComponent(Graphics g)
2115 if (showMemoryUsage && g != null && df != null)
2117 if (percentUsage < 20)
2118 g.setColor(Color.red);
2119 FontMetrics fm = g.getFontMetrics();
2123 "Total Free Memory: " + df.format(totalFreeMemory)
2124 + "MB; Max Memory: " + df.format(maxMemory)
2125 + "MB; " + df.format(percentUsage) + "%", 10,
2126 getHeight() - fm.getHeight());
2133 * fixes stacking order after a modal dialog to ensure windows that should be on top actually are
2135 public void relayerWindows()
2140 protected JMenuItem groovyShell;
2142 public void doGroovyCheck()
2144 if (jalview.bin.Cache.groovyJarsPresent())
2146 groovyShell = new JMenuItem();
2147 groovyShell.setText("Groovy Console...");
2148 groovyShell.addActionListener(new ActionListener()
2150 public void actionPerformed(ActionEvent e)
2152 groovyShell_actionPerformed(e);
2155 toolsMenu.add(groovyShell);
2156 groovyShell.setVisible(true);
2161 * Accessor method to quickly get all the AlignmentFrames loaded.
2163 public static AlignFrame[] getAlignframes()
2165 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2171 Vector avp = new Vector();
2175 for (int i = frames.length - 1; i > -1; i--)
2177 if (frames[i] instanceof AlignFrame)
2179 AlignFrame af = (AlignFrame) frames[i];
2183 } catch (Exception ex)
2185 ex.printStackTrace();
2187 if (avp.size() == 0)
2191 AlignFrame afs[] = new AlignFrame[avp.size()];
2192 for (int i = 0, j = avp.size(); i < j; i++)
2194 afs[i] = (AlignFrame) avp.elementAt(i);
2199 public AppJmol[] getJmols()
2201 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2207 Vector avp = new Vector();
2211 for (int i = frames.length - 1; i > -1; i--)
2213 if (frames[i] instanceof AppJmol)
2215 AppJmol af = (AppJmol) frames[i];
2219 } catch (Exception ex)
2221 ex.printStackTrace();
2223 if (avp.size() == 0)
2227 AppJmol afs[] = new AppJmol[avp.size()];
2228 for (int i = 0, j = avp.size(); i < j; i++)
2230 afs[i] = (AppJmol) avp.elementAt(i);
2237 * Add Groovy Support to Jalview
2239 public void groovyShell_actionPerformed(ActionEvent e)
2241 // use reflection to avoid creating compilation dependency.
2242 if (!jalview.bin.Cache.groovyJarsPresent())
2245 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2249 Class gcClass = Desktop.class.getClassLoader().loadClass(
2250 "groovy.ui.Console");
2251 Constructor gccons = gcClass.getConstructor(null);
2252 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2254 { String.class, Object.class });
2255 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2256 Object gc = gccons.newInstance(null);
2257 setvar.invoke(gc, new Object[]
2258 { "Jalview", this });
2259 run.invoke(gc, null);
2260 } catch (Exception ex)
2262 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2264 .showInternalMessageDialog(
2267 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2268 "Jalview Groovy Support Failed",
2269 JOptionPane.ERROR_MESSAGE);
2274 * Progress bars managed by the IProgressIndicator method.
2276 private Hashtable<Long,JPanel> progressBars;
2277 private Hashtable<Long,IProgressIndicatorHandler> progressBarHandlers;
2282 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2284 public void setProgressBar(String message, long id)
2286 if (progressBars == null)
2288 progressBars = new Hashtable<Long,JPanel>();
2289 progressBarHandlers = new Hashtable<Long,IProgressIndicatorHandler>();
2292 if (progressBars.get(new Long(id)) != null)
2294 JPanel progressPanel = progressBars
2295 .remove(new Long(id));
2296 if (progressBarHandlers.contains(new Long(id)))
2298 progressBarHandlers.remove(new Long(id));
2300 removeProgressPanel(progressPanel);
2304 progressBars.put(new Long(id), addProgressPanel(message));
2311 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2312 * jalview.gui.IProgressIndicatorHandler)
2314 public void registerHandler(final long id,
2315 final IProgressIndicatorHandler handler)
2317 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2320 "call setProgressBar before registering the progress bar's handler.");
2322 progressBarHandlers.put(new Long(id), handler);
2323 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2324 if (handler.canCancel())
2326 JButton cancel = new JButton("Cancel");
2327 final IProgressIndicator us = this;
2328 cancel.addActionListener(new ActionListener()
2331 public void actionPerformed(ActionEvent e)
2333 handler.cancelActivity(id);
2336 + ((JLabel) progressPanel.getComponent(0))
2340 progressPanel.add(cancel, BorderLayout.EAST);
2346 * @return true if any progress bars are still active
2349 public boolean operationInProgress()
2351 if (progressBars != null && progressBars.size() > 0)
2359 * This will return the first AlignFrame viewing AlignViewport av. It will
2360 * break if there are more than one AlignFrames viewing a particular av. This
2363 * @return alignFrame for av
2365 public static AlignFrame getAlignFrameFor(AlignViewport av)
2367 if (desktop != null)
2369 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2370 for (int panel = 0; aps != null && panel < aps.length; panel++)
2372 if (aps[panel] != null && aps[panel].av == av)
2374 return aps[panel].alignFrame;
2381 public VamsasApplication getVamsasApplication()
2388 * flag set if jalview GUI is being operated programmatically
2390 private boolean inBatchMode = false;
2393 * check if jalview GUI is being operated programmatically
2395 * @return inBatchMode
2397 public boolean isInBatchMode()
2403 * set flag if jalview GUI is being operated programmatically
2405 * @param inBatchMode
2407 public void setInBatchMode(boolean inBatchMode)
2409 this.inBatchMode = inBatchMode;
2412 public void startServiceDiscovery()
2414 startServiceDiscovery(false);
2417 public void startServiceDiscovery(boolean blocking)
2419 boolean alive = true;
2420 Thread t0 = null, t1 = null, t2 = null;
2422 // todo: changesupport handlers need to be transferred
2423 if (discoverer == null)
2425 discoverer = new jalview.ws.jws1.Discoverer();
2426 // register PCS handler for desktop.
2427 discoverer.addPropertyChangeListener(changeSupport);
2429 // JAL-940 - disabled JWS1 service configuration - always start discoverer until we phase out completely
2432 (t0 = new Thread(discoverer)).start();
2437 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2439 // EnfinEnvision web service menu entries are rebuild every time the
2440 // menu is shown, so no changeSupport events are needed.
2441 jalview.ws.EnfinEnvision2OneWay.getInstance();
2442 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2445 } catch (Exception e)
2448 .info("Exception when trying to launch Envision2 workflow discovery.",
2450 Cache.log.info(e.getStackTrace());
2452 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2454 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2456 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2458 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2464 // TODO: do rest service discovery
2473 } catch (Exception e)
2476 alive = (t1 != null && t1.isAlive())
2477 || (t2 != null && t2.isAlive())
2478 || (t3 != null && t3.isAlive())
2479 || (t0 != null && t0.isAlive());
2485 * called to check if the service discovery process completed successfully.
2489 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2491 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2493 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2494 .getErrorMessages();
2497 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2499 if (serviceChangedDialog == null)
2501 // only run if we aren't already displaying one of these.
2502 javax.swing.SwingUtilities
2503 .invokeLater(serviceChangedDialog = new Runnable()
2509 .showInternalMessageDialog(
2512 + "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",
2513 "Preferences Problem",
2514 JOptionPane.WARNING_MESSAGE);
2515 serviceChangedDialog = null;
2524 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2531 private Runnable serviceChangedDialog = null;
2534 * start a thread to open a URL in the configured browser. Pops up a warning
2535 * dialog to the user if there is an exception when calling out to the browser
2540 public static void showUrl(final String url)
2542 showUrl(url, Desktop.instance);
2545 * Like showUrl but allows progress handler to be specified
2547 * @param progress (null) or object implementing IProgressIndicator
2549 public static void showUrl(final String url, final IProgressIndicator progress)
2551 new Thread(new Runnable()
2557 if (progress!=null) {
2558 progress.setProgressBar("Opening "+url, this.hashCode());
2560 jalview.util.BrowserLauncher.openURL(url);
2561 } catch (Exception ex)
2564 .showInternalMessageDialog(
2566 "Unixers: Couldn't find default web browser."
2567 + "\nAdd the full path to your browser in Preferences.",
2568 "Web browser not found",
2569 JOptionPane.WARNING_MESSAGE);
2571 ex.printStackTrace();
2573 if (progress!=null) {
2574 progress.setProgressBar(null, this.hashCode());
2580 public static WsParamSetManager wsparamManager = null;
2582 public static ParamManager getUserParameterStore()
2584 if (wsparamManager == null)
2586 wsparamManager = new WsParamSetManager();
2588 return wsparamManager;
2592 * static hyperlink handler proxy method for use by Jalview's internal windows
2595 public static void hyperlinkUpdate(HyperlinkEvent e)
2597 if (e.getEventType() == EventType.ACTIVATED)
2602 url = e.getURL().toString();
2603 Desktop.showUrl(url);
2604 } catch (Exception x)
2607 if (Cache.log!=null) {
2608 Cache.log.error("Couldn't handle string "+url+" as a URL.");
2610 System.err.println("Couldn't handle string "+url+" as a URL.");
2613 // ignore any exceptions due to dud links.
2619 * single thread that handles display of dialogs to user.
2621 ExecutorService dialogExecutor=Executors.newSingleThreadExecutor();
2623 * flag indicating if dialogExecutor should try to acquire a permit
2625 private volatile boolean dialogPause=true;
2629 private java.util.concurrent.Semaphore block=new Semaphore(0);
2632 * add another dialog thread to the queue
2635 public void addDialogThread(final Runnable prompter)
2637 dialogExecutor.submit(new Runnable()
2642 try { block.acquire(); } catch (InterruptedException x){};
2650 SwingUtilities.invokeAndWait(prompter);
2651 } catch (Exception q)
2653 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2659 public void startDialogQueue()
2661 // set the flag so we don't pause waiting for another permit and semaphore the current task to begin