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.JTextArea;
87 import javax.swing.SwingUtilities;
88 import javax.swing.event.HyperlinkEvent;
89 import javax.swing.event.MenuEvent;
90 import javax.swing.event.MenuListener;
91 import javax.swing.event.HyperlinkEvent.EventType;
98 * @version $Revision: 1.155 $
100 public class Desktop extends jalview.jbgui.GDesktop implements
101 DropTargetListener, ClipboardOwner, IProgressIndicator, jalview.api.StructureSelectionManagerProvider
104 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
107 * news reader - null if it was never started.
109 private BlogReader jvnews=null;
113 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
115 public void addJalviewPropertyChangeListener(
116 PropertyChangeListener listener)
118 changeSupport.addJalviewPropertyChangeListener(listener);
122 * @param propertyName
124 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
125 * java.beans.PropertyChangeListener)
127 public void addJalviewPropertyChangeListener(String propertyName,
128 PropertyChangeListener listener)
130 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
134 * @param propertyName
136 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
137 * java.beans.PropertyChangeListener)
139 public void removeJalviewPropertyChangeListener(String propertyName,
140 PropertyChangeListener listener)
142 changeSupport.removeJalviewPropertyChangeListener(propertyName,
146 /** Singleton Desktop instance */
147 public static Desktop instance;
149 public static MyDesktopPane desktop;
151 static int openFrameCount = 0;
153 static final int xOffset = 30;
155 static final int yOffset = 30;
157 public static jalview.ws.jws1.Discoverer discoverer;
159 public static Object[] jalviewClipboard;
161 public static boolean internalCopy = false;
163 static int fileLoadingCount = 0;
165 class MyDesktopManager implements DesktopManager
168 private DesktopManager delegate;
170 public MyDesktopManager(DesktopManager delegate)
172 this.delegate = delegate;
175 public void activateFrame(JInternalFrame f)
179 delegate.activateFrame(f);
180 } catch (NullPointerException npe)
182 Point p = getMousePosition();
183 instance.showPasteMenu(p.x, p.y);
187 public void beginDraggingFrame(JComponent f)
189 delegate.beginDraggingFrame(f);
192 public void beginResizingFrame(JComponent f, int direction)
194 delegate.beginResizingFrame(f, direction);
197 public void closeFrame(JInternalFrame f)
199 delegate.closeFrame(f);
202 public void deactivateFrame(JInternalFrame f)
204 delegate.deactivateFrame(f);
207 public void deiconifyFrame(JInternalFrame f)
209 delegate.deiconifyFrame(f);
212 public void dragFrame(JComponent f, int newX, int newY)
218 delegate.dragFrame(f, newX, newY);
221 public void endDraggingFrame(JComponent f)
223 delegate.endDraggingFrame(f);
226 public void endResizingFrame(JComponent f)
228 delegate.endResizingFrame(f);
231 public void iconifyFrame(JInternalFrame f)
233 delegate.iconifyFrame(f);
236 public void maximizeFrame(JInternalFrame f)
238 delegate.maximizeFrame(f);
241 public void minimizeFrame(JInternalFrame f)
243 delegate.minimizeFrame(f);
246 public void openFrame(JInternalFrame f)
248 delegate.openFrame(f);
251 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
254 Rectangle b=desktop.getBounds();
259 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
262 public void setBoundsForFrame(JComponent f, int newX, int newY,
263 int newWidth, int newHeight)
265 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
268 // All other methods, simply delegate
273 * Creates a new Desktop object.
278 * A note to implementors. It is ESSENTIAL that any activities that might
279 * block are spawned off as threads rather than waited for during this
283 doVamsasClientCheck();
286 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
287 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
288 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
290 boolean showjconsole = jalview.bin.Cache.getDefault(
291 "SHOW_JAVA_CONSOLE", false);
292 desktop = new MyDesktopPane(selmemusage);
293 showMemusage.setSelected(selmemusage);
294 desktop.setBackground(Color.white);
295 getContentPane().setLayout(new BorderLayout());
296 // alternate config - have scrollbars - see notes in JAL-153
297 //JScrollPane sp = new JScrollPane();
298 //sp.getViewport().setView(desktop);
299 //getContentPane().add(sp, BorderLayout.CENTER);
300 getContentPane().add(desktop, BorderLayout.CENTER);
301 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
304 // This line prevents Windows Look&Feel resizing all new windows to maximum
305 // if previous window was maximised
306 desktop.setDesktopManager(new MyDesktopManager(
307 new DefaultDesktopManager()));
309 Rectangle dims = getLastKnownDimensions("");
316 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
317 setBounds((int) (screenSize.width - 900) / 2,
318 (int) (screenSize.height - 650) / 2, 900, 650);
320 jconsole = new Console(this, showjconsole);
321 // add essential build information
322 jconsole.setHeader("Jalview Desktop "
323 + jalview.bin.Cache.getProperty("VERSION") + "\n"
325 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
326 + "Java version: " + System.getProperty("java.version") + "\n"
327 + System.getProperty("os.arch") + " "
328 + System.getProperty("os.name") + " "
329 + System.getProperty("os.version"));
331 showConsole(showjconsole);
333 showNews.setVisible(false);
335 this.addWindowListener(new WindowAdapter()
337 public void windowClosing(WindowEvent evt)
344 this.addMouseListener(ma=new MouseAdapter()
346 public void mousePressed(MouseEvent evt)
348 if (SwingUtilities.isRightMouseButton(evt))
350 showPasteMenu(evt.getX(), evt.getY());
354 desktop.addMouseListener(ma);
356 this.addFocusListener(new FocusListener()
360 public void focusLost(FocusEvent e)
362 // TODO Auto-generated method stub
367 public void focusGained(FocusEvent e)
369 Cache.log.debug("Relaying windows after focus gain");
370 // make sure that we sort windows properly after we gain focus
371 instance.relayerWindows();
374 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
375 // Spawn a thread that shows the splashscreen
376 SwingUtilities.invokeLater(new Runnable()
385 // Thread off a new instance of the file chooser - this reduces the time it
386 // takes to open it later on.
387 new Thread(new Runnable()
391 Cache.log.debug("Filechooser init thread started.");
392 JalviewFileChooser chooser = new JalviewFileChooser(
393 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
394 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
395 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
396 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
397 Cache.log.debug("Filechooser init thread finished.");
400 // Add the service change listener
401 changeSupport.addJalviewPropertyChangeListener("services",
402 new PropertyChangeListener()
406 public void propertyChange(PropertyChangeEvent evt)
408 Cache.log.debug("Firing service changed event for "
409 + evt.getNewValue());
410 JalviewServicesChanged(evt);
416 public void checkForNews()
418 final Desktop me = this;
419 // Thread off the news reader, in case there are connection problems.
420 addDialogThread(new Runnable() {
424 Cache.log.debug("Starting news thread.");
426 jvnews = new BlogReader(me);
427 showNews.setVisible(true);
428 Cache.log.debug("Completed news thread.");
432 protected void showNews_actionPerformed(ActionEvent e)
434 showNews(showNews.isSelected());
436 void showNews(boolean visible)
439 Cache.log.debug((visible?"Showing":"Hiding")+" news.");
440 showNews.setSelected(visible);
441 if (visible && !jvnews.isVisible())
443 new Thread(new Runnable() {
447 long instance=System.currentTimeMillis();
448 Desktop.instance.setProgressBar("Refreshing news", instance);
449 jvnews.refreshNews();
450 Desktop.instance.setProgressBar(null, instance);
459 * recover the last known dimensions for a jalview window
462 * - empty string is desktop, all other windows have unique prefix
463 * @return null or last known dimensions scaled to current geometry (if last
464 * window geom was known)
466 Rectangle getLastKnownDimensions(String windowName)
468 // TODO: lock aspect ratio for scaling desktop Bug #0058199
469 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
470 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
471 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
472 String width = jalview.bin.Cache.getProperty(windowName
474 String height = jalview.bin.Cache.getProperty(windowName
476 if ((x != null) && (y != null) && (width != null) && (height != null))
478 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
479 .parseInt(width), ih = Integer.parseInt(height);
480 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
482 // attempt #1 - try to cope with change in screen geometry - this
483 // version doesn't preserve original jv aspect ratio.
484 // take ratio of current screen size vs original screen size.
485 double sw = ((1f * screenSize.width) / (1f * Integer
486 .parseInt(jalview.bin.Cache
487 .getProperty("SCREENGEOMETRY_WIDTH"))));
488 double sh = ((1f * screenSize.height) / (1f * Integer
489 .parseInt(jalview.bin.Cache
490 .getProperty("SCREENGEOMETRY_HEIGHT"))));
491 // rescale the bounds depending upon the current screen geometry.
492 ix = (int) (ix * sw);
493 iw = (int) (iw * sw);
494 iy = (int) (iy * sh);
495 ih = (int) (ih * sh);
496 while (ix >= screenSize.width)
498 jalview.bin.Cache.log
499 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
500 ix -= screenSize.width;
502 while (iy >= screenSize.height)
504 jalview.bin.Cache.log
505 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
506 iy -= screenSize.height;
508 jalview.bin.Cache.log.debug("Got last known dimensions for "
509 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
512 // return dimensions for new instance
513 return new Rectangle(ix, iy, iw, ih);
518 private void doVamsasClientCheck()
520 if (jalview.bin.Cache.vamsasJarsPresent())
522 setupVamsasDisconnectedGui();
523 VamsasMenu.setVisible(true);
524 final Desktop us = this;
525 VamsasMenu.addMenuListener(new MenuListener()
527 // this listener remembers when the menu was first selected, and
528 // doesn't rebuild the session list until it has been cleared and
530 boolean refresh = true;
532 public void menuCanceled(MenuEvent e)
537 public void menuDeselected(MenuEvent e)
542 public void menuSelected(MenuEvent e)
546 us.buildVamsasStMenu();
551 vamsasStart.setVisible(true);
555 void showPasteMenu(int x, int y)
557 JPopupMenu popup = new JPopupMenu();
558 JMenuItem item = new JMenuItem("Paste To New Window");
559 item.addActionListener(new ActionListener()
561 public void actionPerformed(ActionEvent evt)
568 popup.show(this, x, y);
575 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
576 Transferable contents = c.getContents(this);
578 if (contents != null)
580 String file = (String) contents
581 .getTransferData(DataFlavor.stringFlavor);
583 String format = new IdentifyFile().Identify(file,
584 FormatAdapter.PASTE);
586 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
589 } catch (Exception ex)
592 .println("Unable to paste alignment from system clipboard:\n"
598 * Adds and opens the given frame to the desktop
609 public static synchronized void addInternalFrame(
610 final JInternalFrame frame, String title, int w, int h)
612 addInternalFrame(frame, title, w, h, true);
629 public static synchronized void addInternalFrame(
630 final JInternalFrame frame, String title, int w, int h,
634 // TODO: allow callers to determine X and Y position of frame (eg. via
636 // TODO: consider fixing method to update entries in the window submenu with
637 // the current window title
639 frame.setTitle(title);
640 if (frame.getWidth() < 1 || frame.getHeight() < 1)
644 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
645 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
646 // IF JALVIEW IS RUNNING HEADLESS
647 // ///////////////////////////////////////////////
648 if (System.getProperty("java.awt.headless") != null
649 && System.getProperty("java.awt.headless").equals("true"))
656 frame.setVisible(true);
657 frame.setClosable(true);
658 frame.setResizable(resizable);
659 frame.setMaximizable(resizable);
660 frame.setIconifiable(resizable);
661 frame.setFrameIcon(null);
663 if (frame.getX() < 1 && frame.getY() < 1)
665 frame.setLocation(xOffset * openFrameCount, yOffset
666 * ((openFrameCount - 1) % 10) + yOffset);
669 final JMenuItem menuItem = new JMenuItem(title);
670 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
672 public void internalFrameActivated(
673 javax.swing.event.InternalFrameEvent evt)
675 JInternalFrame itf = desktop.getSelectedFrame();
683 public void internalFrameClosed(
684 javax.swing.event.InternalFrameEvent evt)
686 PaintRefresher.RemoveComponent(frame);
688 windowMenu.remove(menuItem);
689 JInternalFrame itf = desktop.getSelectedFrame();
698 menuItem.addActionListener(new ActionListener()
700 public void actionPerformed(ActionEvent e)
704 frame.setSelected(true);
705 frame.setIcon(false);
706 } catch (java.beans.PropertyVetoException ex)
712 menuItem.addMouseListener(new MouseListener()
716 public void mouseReleased(MouseEvent e)
721 public void mousePressed(MouseEvent e)
726 public void mouseExited(MouseEvent e)
730 frame.setSelected(false);
731 } catch (PropertyVetoException e1)
737 public void mouseEntered(MouseEvent e)
741 frame.setSelected(true);
742 } catch (PropertyVetoException e1)
748 public void mouseClicked(MouseEvent e)
754 windowMenu.add(menuItem);
760 frame.setSelected(true);
761 frame.requestFocus();
762 } catch (java.beans.PropertyVetoException ve)
765 catch (java.lang.ClassCastException cex)
767 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);
771 public void lostOwnership(Clipboard clipboard, Transferable contents)
775 Desktop.jalviewClipboard = null;
778 internalCopy = false;
781 public void dragEnter(DropTargetDragEvent evt)
785 public void dragExit(DropTargetEvent evt)
789 public void dragOver(DropTargetDragEvent evt)
793 public void dropActionChanged(DropTargetDragEvent evt)
803 public void drop(DropTargetDropEvent evt)
805 Transferable t = evt.getTransferable();
806 java.util.List files = null;
807 java.util.List protocols = null;
811 DataFlavor uriListFlavor = new DataFlavor(
812 "text/uri-list;class=java.lang.String");
813 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
815 // Works on Windows and MacOSX
816 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
817 files = (java.util.List) t
818 .getTransferData(DataFlavor.javaFileListFlavor);
820 else if (t.isDataFlavorSupported(uriListFlavor))
822 // This is used by Unix drag system
823 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
824 String data = (String) t.getTransferData(uriListFlavor);
825 files = new java.util.ArrayList(1);
826 protocols = new java.util.ArrayList(1);
827 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
828 data, "\r\n"); st.hasMoreTokens();)
830 String s = st.nextToken();
831 if (s.startsWith("#"))
833 // the line is a comment (as per the RFC 2483)
836 java.net.URI uri = new java.net.URI(s);
837 if (uri.getScheme().toLowerCase().startsWith("http"))
839 protocols.add(FormatAdapter.URL);
840 files.add(uri.toString());
844 // otherwise preserve old behaviour: catch all for file objects
845 java.io.File file = new java.io.File(uri);
846 protocols.add(FormatAdapter.FILE);
847 files.add(file.toString());
851 } catch (Exception e)
859 for (int i = 0; i < files.size(); i++)
861 String file = files.get(i).toString();
862 String protocol = (protocols == null) ? FormatAdapter.FILE
863 : (String) protocols.get(i);
864 String format = null;
866 if (file.endsWith(".jar"))
873 format = new IdentifyFile().Identify(file, protocol);
876 new FileLoader().LoadFile(file, protocol, format);
879 } catch (Exception ex)
891 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
893 JalviewFileChooser chooser = new JalviewFileChooser(
894 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
895 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
896 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
897 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
899 chooser.setFileView(new JalviewFileView());
900 chooser.setDialogTitle("Open local file");
901 chooser.setToolTipText("Open");
903 int value = chooser.showOpenDialog(this);
905 if (value == JalviewFileChooser.APPROVE_OPTION)
907 String choice = chooser.getSelectedFile().getPath();
908 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
909 .getSelectedFile().getParent());
911 String format = null;
912 if (chooser.getSelectedFormat().equals("Jalview"))
918 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
921 if (viewport != null)
923 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
928 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
939 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
941 // This construct allows us to have a wider textfield
943 JLabel label = new JLabel("Enter URL of Input File");
944 final JComboBox history = new JComboBox();
946 JPanel panel = new JPanel(new GridLayout(2, 1));
949 history.setPreferredSize(new Dimension(400, 20));
950 history.setEditable(true);
951 history.addItem("http://www.");
953 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
957 if (historyItems != null)
959 st = new StringTokenizer(historyItems, "\t");
961 while (st.hasMoreTokens())
963 history.addItem(st.nextElement());
967 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
968 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
970 if (reply != JOptionPane.OK_OPTION)
975 String url = history.getSelectedItem().toString();
977 if (url.toLowerCase().endsWith(".jar"))
979 if (viewport != null)
981 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
986 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
991 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
993 if (format.equals("URL NOT FOUND"))
995 JOptionPane.showInternalMessageDialog(Desktop.desktop,
996 "Couldn't locate " + url, "URL not found",
997 JOptionPane.WARNING_MESSAGE);
1002 if (viewport != null)
1004 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1008 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1019 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1021 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1022 cap.setForInput(viewport);
1023 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1031 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1033 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1034 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1036 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1037 getBounds().y, getWidth(), getHeight()));
1039 if (jconsole != null)
1041 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1042 jconsole.stopConsole();
1046 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1049 if (dialogExecutor!=null)
1051 dialogExecutor.shutdownNow();
1057 private void storeLastKnownDimensions(String string, Rectangle jc)
1059 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1060 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1061 + " height:" + jc.height);
1063 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1064 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1065 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1066 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1075 public void aboutMenuItem_actionPerformed(ActionEvent e)
1077 // StringBuffer message = getAboutMessage(false);
1078 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1080 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1081 new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
1084 public StringBuffer getAboutMessage(boolean shortv)
1086 StringBuffer message = new StringBuffer();
1087 message.append("<html>");
1090 message.append("<h1><strong>Version: "
1091 + jalview.bin.Cache.getProperty("VERSION")
1092 + "</strong></h1><br>");
1093 message.append("<strong>Last Updated: <em>"
1094 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1095 + "</em></strong>");
1101 message.append("<strong>Version "
1102 + jalview.bin.Cache.getProperty("VERSION")
1103 + "; last updated: "
1104 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1107 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1110 message.append("<br>...Checking latest version...</br>");
1112 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1113 .equals(jalview.bin.Cache.getProperty("VERSION")))
1115 boolean red = false;
1116 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1117 .indexOf("automated build") == -1)
1120 // Displayed when code version and jnlp version do not match and code
1121 // version is not a development build
1122 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1125 message.append("<br>!! Version "
1126 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1128 + " is available for download from "
1129 + jalview.bin.Cache.getDefault("www.jalview.org",
1130 "http://www.jalview.org") + " !!");
1133 message.append("</div>");
1136 message.append("<br>Authors: "
1140 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1141 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1142 + "<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"
1143 + "<br>If you use Jalview, please cite:"
1144 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1145 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1146 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1157 public void documentationMenuItem_actionPerformed(ActionEvent e)
1161 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1162 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1163 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1165 javax.help.HelpBroker hb = hs.createHelpBroker();
1166 hb.setCurrentID("home");
1167 hb.setDisplayed(true);
1168 } catch (Exception ex)
1173 public void closeAll_actionPerformed(ActionEvent e)
1175 JInternalFrame[] frames = desktop.getAllFrames();
1176 for (int i = 0; i < frames.length; i++)
1180 frames[i].setClosed(true);
1181 } catch (java.beans.PropertyVetoException ex)
1185 System.out.println("ALL CLOSED");
1186 if (v_client != null)
1188 // TODO clear binding to vamsas document objects on close_all
1193 public void raiseRelated_actionPerformed(ActionEvent e)
1195 reorderAssociatedWindows(false, false);
1198 public void minimizeAssociated_actionPerformed(ActionEvent e)
1200 reorderAssociatedWindows(true, false);
1203 void closeAssociatedWindows()
1205 reorderAssociatedWindows(false, true);
1211 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1214 protected void garbageCollect_actionPerformed(ActionEvent e)
1216 // We simply collect the garbage
1217 jalview.bin.Cache.log.debug("Collecting garbage...");
1219 jalview.bin.Cache.log.debug("Finished garbage collection.");
1226 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1229 protected void showMemusage_actionPerformed(ActionEvent e)
1231 desktop.showMemoryUsage(showMemusage.isSelected());
1238 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1241 protected void showConsole_actionPerformed(ActionEvent e)
1243 showConsole(showConsole.isSelected());
1246 Console jconsole = null;
1249 * control whether the java console is visible or not
1253 void showConsole(boolean selected)
1255 showConsole.setSelected(selected);
1256 // TODO: decide if we should update properties file
1257 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1259 jconsole.setVisible(selected);
1262 void reorderAssociatedWindows(boolean minimize, boolean close)
1264 JInternalFrame[] frames = desktop.getAllFrames();
1265 if (frames == null || frames.length < 1)
1270 AlignViewport source = null, target = null;
1271 if (frames[0] instanceof AlignFrame)
1273 source = ((AlignFrame) frames[0]).getCurrentView();
1275 else if (frames[0] instanceof TreePanel)
1277 source = ((TreePanel) frames[0]).getViewPort();
1279 else if (frames[0] instanceof PCAPanel)
1281 source = ((PCAPanel) frames[0]).av;
1283 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1285 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1290 for (int i = 0; i < frames.length; i++)
1293 if (frames[i] == null)
1297 if (frames[i] instanceof AlignFrame)
1299 target = ((AlignFrame) frames[i]).getCurrentView();
1301 else if (frames[i] instanceof TreePanel)
1303 target = ((TreePanel) frames[i]).getViewPort();
1305 else if (frames[i] instanceof PCAPanel)
1307 target = ((PCAPanel) frames[i]).av;
1309 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1311 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1314 if (source == target)
1320 frames[i].setClosed(true);
1324 frames[i].setIcon(minimize);
1327 frames[i].toFront();
1331 } catch (java.beans.PropertyVetoException ex)
1345 protected void preferences_actionPerformed(ActionEvent e)
1356 public void saveState_actionPerformed(ActionEvent e)
1358 JalviewFileChooser chooser = new JalviewFileChooser(
1359 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1360 { "jar" }, new String[]
1361 { "Jalview Project" }, "Jalview Project");
1363 chooser.setFileView(new JalviewFileView());
1364 chooser.setDialogTitle("Save State");
1366 int value = chooser.showSaveDialog(this);
1368 if (value == JalviewFileChooser.APPROVE_OPTION)
1370 final Desktop me = this;
1371 final java.io.File choice = chooser.getSelectedFile();
1372 new Thread(new Runnable()
1377 setProgressBar("Saving jalview project " + choice.getName(),
1379 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1380 // TODO catch and handle errors for savestate
1381 // TODO prevent user from messing with the Desktop whilst we're saving
1384 new Jalview2XML().SaveState(choice);
1385 } catch (OutOfMemoryError oom)
1388 "Whilst saving current state to " + choice.getName(), oom);
1389 } catch (Exception ex)
1392 .error("Problems whilst trying to save to "
1393 + choice.getName(), ex);
1394 JOptionPane.showMessageDialog(me,
1395 "Error whilst saving current state to " + choice.getName(),
1396 "Couldn't save project", JOptionPane.WARNING_MESSAGE);
1398 setProgressBar(null, choice.hashCode());
1410 public void loadState_actionPerformed(ActionEvent e)
1412 JalviewFileChooser chooser = new JalviewFileChooser(
1413 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1414 { "jar" }, new String[]
1415 { "Jalview Project" }, "Jalview Project");
1416 chooser.setFileView(new JalviewFileView());
1417 chooser.setDialogTitle("Restore state");
1419 int value = chooser.showOpenDialog(this);
1421 if (value == JalviewFileChooser.APPROVE_OPTION)
1423 final String choice = chooser.getSelectedFile().getAbsolutePath();
1424 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1425 .getSelectedFile().getParent());
1426 new Thread(new Runnable()
1430 setProgressBar("loading jalview project " + choice,
1434 new Jalview2XML().LoadJalviewAlign(choice);
1435 } catch (OutOfMemoryError oom)
1437 new OOMWarning("Whilst loading project from " + choice, oom);
1438 } catch (Exception ex)
1440 Cache.log.error("Problems whilst loading project from "
1442 JOptionPane.showMessageDialog(Desktop.desktop,
1443 "Error whilst loading project from " + choice,
1444 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1446 setProgressBar(null, choice.hashCode());
1452 public void inputSequence_actionPerformed(ActionEvent e)
1454 new SequenceFetcher(this);
1457 JPanel progressPanel;
1458 ArrayList<JPanel> fileLoadingPanels=new ArrayList<JPanel>();
1459 public void startLoading(final String fileName)
1461 if (fileLoadingCount == 0)
1463 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName + " "));
1468 private JPanel addProgressPanel(String string)
1470 if (progressPanel == null)
1472 progressPanel = new JPanel(new GridLayout(1,1));
1473 totalProgressCount = 0;
1474 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1476 JPanel thisprogress=new JPanel(new BorderLayout(10,5));
1477 JProgressBar progressBar = new JProgressBar();
1478 progressBar.setIndeterminate(true);
1480 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1482 thisprogress.add(progressBar, BorderLayout.CENTER);
1483 progressPanel.add(thisprogress);
1484 ((GridLayout)progressPanel.getLayout()).setRows(((GridLayout)progressPanel.getLayout()).getRows()+1);
1485 ++totalProgressCount;
1486 instance.validate();
1487 return thisprogress;
1490 int totalProgressCount = 0;
1492 private void removeProgressPanel(JPanel progbar)
1494 if (progressPanel != null)
1496 progressPanel.remove(progbar);
1497 GridLayout gl = (GridLayout) progressPanel.getLayout();
1498 gl.setRows(gl.getRows()-1);
1499 if (--totalProgressCount < 1)
1501 this.getContentPane().remove(progressPanel);
1502 progressPanel = null;
1508 public void stopLoading()
1511 if (fileLoadingCount < 1)
1513 for (JPanel flp : fileLoadingPanels)
1515 removeProgressPanel(flp);
1517 fileLoadingPanels.clear();
1518 fileLoadingCount = 0;
1523 public static int getViewCount(String alignmentId)
1525 AlignViewport[] aps = getViewports(alignmentId);
1526 return (aps == null) ? 0 : aps.length;
1531 * @param alignmentId
1532 * @return all AlignmentPanels concerning the alignmentId sequence set
1534 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1537 if (Desktop.desktop == null)
1539 // no frames created and in headless mode
1540 // TODO: verify that frames are recoverable when in headless mode
1543 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1544 ArrayList aps = new ArrayList();
1545 for (int t = 0; t < frames.length; t++)
1547 if (frames[t] instanceof AlignFrame)
1549 AlignFrame af = (AlignFrame) frames[t];
1550 for (int a = 0; a < af.alignPanels.size(); a++)
1553 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1554 .getSequenceSetId()))
1556 aps.add(af.alignPanels.elementAt(a));
1561 if (aps.size() == 0)
1565 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1566 for (int t = 0; t < vap.length; t++)
1568 vap[t] = (AlignmentPanel) aps.get(t);
1574 * get all the viewports on an alignment.
1576 * @param sequenceSetId
1577 * unique alignment id
1578 * @return all viewports on the alignment bound to sequenceSetId
1580 public static AlignViewport[] getViewports(String sequenceSetId)
1582 Vector viewp = new Vector();
1583 if (desktop != null)
1585 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1587 for (int t = 0; t < frames.length; t++)
1589 if (frames[t] instanceof AlignFrame)
1591 AlignFrame afr = ((AlignFrame) frames[t]);
1592 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1594 if (afr.alignPanels != null)
1596 for (int a = 0; a < afr.alignPanels.size(); a++)
1598 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1599 .elementAt(a)).av.getSequenceSetId()))
1601 viewp.addElement(((AlignmentPanel) afr.alignPanels
1608 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1613 if (viewp.size() > 0)
1615 AlignViewport[] vp = new AlignViewport[viewp.size()];
1623 public void explodeViews(AlignFrame af)
1625 int size = af.alignPanels.size();
1631 for (int i = 0; i < size; i++)
1633 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1634 AlignFrame newaf = new AlignFrame(ap);
1635 if (ap.av.explodedPosition != null
1636 && !ap.av.explodedPosition.equals(af.getBounds()))
1638 newaf.setBounds(ap.av.explodedPosition);
1641 ap.av.gatherViewsHere = false;
1643 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1644 AlignFrame.DEFAULT_HEIGHT);
1647 af.alignPanels.clear();
1648 af.closeMenuItem_actionPerformed(true);
1652 public void gatherViews(AlignFrame source)
1654 source.viewport.gatherViewsHere = true;
1655 source.viewport.explodedPosition = source.getBounds();
1656 JInternalFrame[] frames = desktop.getAllFrames();
1657 String viewId = source.viewport.getSequenceSetId();
1659 for (int t = 0; t < frames.length; t++)
1661 if (frames[t] instanceof AlignFrame && frames[t] != source)
1663 AlignFrame af = (AlignFrame) frames[t];
1664 boolean gatherThis = false;
1665 for (int a = 0; a < af.alignPanels.size(); a++)
1667 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1668 if (viewId.equals(ap.av.getSequenceSetId()))
1671 ap.av.gatherViewsHere = false;
1672 ap.av.explodedPosition = af.getBounds();
1673 source.addAlignmentPanel(ap, false);
1679 af.alignPanels.clear();
1680 af.closeMenuItem_actionPerformed(true);
1687 jalview.gui.VamsasApplication v_client = null;
1689 public void vamsasImport_actionPerformed(ActionEvent e)
1691 if (v_client == null)
1693 // Load and try to start a session.
1694 JalviewFileChooser chooser = new JalviewFileChooser(
1695 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1697 chooser.setFileView(new JalviewFileView());
1698 chooser.setDialogTitle("Open a saved VAMSAS session");
1699 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1701 int value = chooser.showOpenDialog(this);
1703 if (value == JalviewFileChooser.APPROVE_OPTION)
1705 String fle = chooser.getSelectedFile().toString();
1706 if (!vamsasImport(chooser.getSelectedFile()))
1708 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1709 "Couldn't import '" + fle + "' as a new vamsas session.",
1710 "Vamsas Document Import Failed",
1711 JOptionPane.ERROR_MESSAGE);
1717 jalview.bin.Cache.log
1718 .error("Implementation error - load session from a running session is not supported.");
1723 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1726 * @return true if import was a success and a session was started.
1728 public boolean vamsasImport(URL url)
1730 // TODO: create progress bar
1731 if (v_client != null)
1734 jalview.bin.Cache.log
1735 .error("Implementation error - load session from a running session is not supported.");
1741 // copy the URL content to a temporary local file
1742 // TODO: be a bit cleverer here with nio (?!)
1743 File file = File.createTempFile("vdocfromurl", ".vdj");
1744 FileOutputStream fos = new FileOutputStream(file);
1745 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1746 byte[] buffer = new byte[2048];
1748 while ((ln = bis.read(buffer)) > -1)
1750 fos.write(buffer, 0, ln);
1754 v_client = new jalview.gui.VamsasApplication(this, file,
1755 url.toExternalForm());
1756 } catch (Exception ex)
1758 jalview.bin.Cache.log.error(
1759 "Failed to create new vamsas session from contents of URL "
1763 setupVamsasConnectedGui();
1764 v_client.initial_update(); // TODO: thread ?
1765 return v_client.inSession();
1769 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1772 * @return true if import was a success and a session was started.
1774 public boolean vamsasImport(File file)
1776 if (v_client != null)
1779 jalview.bin.Cache.log
1780 .error("Implementation error - load session from a running session is not supported.");
1784 setProgressBar("Importing VAMSAS session from " + file.getName(),
1788 v_client = new jalview.gui.VamsasApplication(this, file, null);
1789 } catch (Exception ex)
1791 setProgressBar("Importing VAMSAS session from " + file.getName(),
1793 jalview.bin.Cache.log.error(
1794 "New vamsas session from existing session file failed:", ex);
1797 setupVamsasConnectedGui();
1798 v_client.initial_update(); // TODO: thread ?
1799 setProgressBar("Importing VAMSAS session from " + file.getName(),
1801 return v_client.inSession();
1804 public boolean joinVamsasSession(String mysesid)
1806 if (v_client != null)
1809 "Trying to join a vamsas session when another is already connected.");
1811 if (mysesid == null)
1813 throw new Error("Invalid vamsas session id.");
1815 v_client = new VamsasApplication(this, mysesid);
1816 setupVamsasConnectedGui();
1817 v_client.initial_update();
1818 return (v_client.inSession());
1821 public void vamsasStart_actionPerformed(ActionEvent e)
1823 if (v_client == null)
1826 // we just start a default session for moment.
1828 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1829 * getProperty("LAST_DIRECTORY"));
1831 * chooser.setFileView(new JalviewFileView());
1832 * chooser.setDialogTitle("Load Vamsas file");
1833 * chooser.setToolTipText("Import");
1835 * int value = chooser.showOpenDialog(this);
1837 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1838 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1840 v_client = new VamsasApplication(this);
1841 setupVamsasConnectedGui();
1842 v_client.initial_update(); // TODO: thread ?
1846 // store current data in session.
1847 v_client.push_update(); // TODO: thread
1851 protected void setupVamsasConnectedGui()
1853 vamsasStart.setText("Session Update");
1854 vamsasSave.setVisible(true);
1855 vamsasStop.setVisible(true);
1856 vamsasImport.setVisible(false); // Document import to existing session is
1857 // not possible for vamsas-client-1.0.
1860 protected void setupVamsasDisconnectedGui()
1862 vamsasSave.setVisible(false);
1863 vamsasStop.setVisible(false);
1864 vamsasImport.setVisible(true);
1865 vamsasStart.setText("New Vamsas Session");
1868 public void vamsasStop_actionPerformed(ActionEvent e)
1870 if (v_client != null)
1872 v_client.end_session();
1874 setupVamsasDisconnectedGui();
1878 protected void buildVamsasStMenu()
1880 if (v_client == null)
1882 String[] sess = null;
1885 sess = VamsasApplication.getSessionList();
1886 } catch (Exception e)
1888 jalview.bin.Cache.log.warn(
1889 "Problem getting current sessions list.", e);
1894 jalview.bin.Cache.log.debug("Got current sessions list: "
1895 + sess.length + " entries.");
1896 VamsasStMenu.removeAll();
1897 for (int i = 0; i < sess.length; i++)
1899 JMenuItem sessit = new JMenuItem();
1900 sessit.setText(sess[i]);
1901 sessit.setToolTipText("Connect to session " + sess[i]);
1902 final Desktop dsktp = this;
1903 final String mysesid = sess[i];
1904 sessit.addActionListener(new ActionListener()
1907 public void actionPerformed(ActionEvent e)
1909 if (dsktp.v_client == null)
1911 Thread rthr = new Thread(new Runnable()
1916 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1917 dsktp.setupVamsasConnectedGui();
1918 dsktp.v_client.initial_update();
1926 VamsasStMenu.add(sessit);
1928 // don't show an empty menu.
1929 VamsasStMenu.setVisible(sess.length > 0);
1934 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1935 VamsasStMenu.removeAll();
1936 VamsasStMenu.setVisible(false);
1941 // Not interested in the content. Just hide ourselves.
1942 VamsasStMenu.setVisible(false);
1946 public void vamsasSave_actionPerformed(ActionEvent e)
1948 if (v_client != null)
1950 JalviewFileChooser chooser = new JalviewFileChooser(
1951 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1952 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1954 { "Vamsas Document" }, "Vamsas Document");
1956 chooser.setFileView(new JalviewFileView());
1957 chooser.setDialogTitle("Save Vamsas Document Archive");
1959 int value = chooser.showSaveDialog(this);
1961 if (value == JalviewFileChooser.APPROVE_OPTION)
1963 java.io.File choice = chooser.getSelectedFile();
1964 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1965 + choice.getName());
1966 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1967 String warnmsg = null;
1968 String warnttl = null;
1971 v_client.vclient.storeDocument(choice);
1974 warnttl = "Serious Problem saving Vamsas Document";
1975 warnmsg = ex.toString();
1976 jalview.bin.Cache.log.error("Error Whilst saving document to "
1979 } catch (Exception ex)
1981 warnttl = "Problem saving Vamsas Document.";
1982 warnmsg = ex.toString();
1983 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1987 removeProgressPanel(progpanel);
1988 if (warnmsg != null)
1990 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1992 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1998 JPanel vamUpdate = null;
2001 * hide vamsas user gui bits when a vamsas document event is being handled.
2004 * true to hide gui, false to reveal gui
2006 public void setVamsasUpdate(boolean b)
2008 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2009 + (b ? "in progress" : "finished"));
2011 if (vamUpdate != null)
2013 this.removeProgressPanel(vamUpdate);
2017 vamUpdate = this.addProgressPanel("Updating vamsas session");
2019 vamsasStart.setVisible(!b);
2020 vamsasStop.setVisible(!b);
2021 vamsasSave.setVisible(!b);
2024 public JInternalFrame[] getAllFrames()
2026 return desktop.getAllFrames();
2030 * Checks the given url to see if it gives a response indicating that the user
2031 * should be informed of a new questionnaire.
2035 public void checkForQuestionnaire(String url)
2037 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2038 // javax.swing.SwingUtilities.invokeLater(jvq);
2039 new Thread(jvq).start();
2043 * Proxy class for JDesktopPane which optionally displays the current memory
2044 * usage and highlights the desktop area with a red bar if free memory runs
2049 public class MyDesktopPane extends JDesktopPane implements Runnable
2052 boolean showMemoryUsage = false;
2056 java.text.NumberFormat df;
2058 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2061 public MyDesktopPane(boolean showMemoryUsage)
2063 showMemoryUsage(showMemoryUsage);
2066 public void showMemoryUsage(boolean showMemoryUsage)
2068 this.showMemoryUsage = showMemoryUsage;
2069 if (showMemoryUsage)
2071 Thread worker = new Thread(this);
2076 public boolean isShowMemoryUsage()
2078 return showMemoryUsage;
2083 df = java.text.NumberFormat.getNumberInstance();
2084 df.setMaximumFractionDigits(2);
2085 runtime = Runtime.getRuntime();
2087 while (showMemoryUsage)
2091 maxMemory = runtime.maxMemory() / 1048576f;
2092 allocatedMemory = runtime.totalMemory() / 1048576f;
2093 freeMemory = runtime.freeMemory() / 1048576f;
2094 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2096 percentUsage = (totalFreeMemory / maxMemory) * 100;
2098 // if (percentUsage < 20)
2100 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2102 // instance.set.setBorder(border1);
2105 // sleep after showing usage
2107 } catch (Exception ex)
2109 ex.printStackTrace();
2114 public void paintComponent(Graphics g)
2116 if (showMemoryUsage && g != null && df != null)
2118 if (percentUsage < 20)
2119 g.setColor(Color.red);
2120 FontMetrics fm = g.getFontMetrics();
2124 "Total Free Memory: " + df.format(totalFreeMemory)
2125 + "MB; Max Memory: " + df.format(maxMemory)
2126 + "MB; " + df.format(percentUsage) + "%", 10,
2127 getHeight() - fm.getHeight());
2134 * fixes stacking order after a modal dialog to ensure windows that should be on top actually are
2136 public void relayerWindows()
2141 protected JMenuItem groovyShell;
2143 public void doGroovyCheck()
2145 if (jalview.bin.Cache.groovyJarsPresent())
2147 groovyShell = new JMenuItem();
2148 groovyShell.setText("Groovy Console...");
2149 groovyShell.addActionListener(new ActionListener()
2151 public void actionPerformed(ActionEvent e)
2153 groovyShell_actionPerformed(e);
2156 toolsMenu.add(groovyShell);
2157 groovyShell.setVisible(true);
2162 * Accessor method to quickly get all the AlignmentFrames loaded.
2164 public static AlignFrame[] getAlignframes()
2166 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2172 Vector avp = new Vector();
2176 for (int i = frames.length - 1; i > -1; i--)
2178 if (frames[i] instanceof AlignFrame)
2180 AlignFrame af = (AlignFrame) frames[i];
2184 } catch (Exception ex)
2186 ex.printStackTrace();
2188 if (avp.size() == 0)
2192 AlignFrame afs[] = new AlignFrame[avp.size()];
2193 for (int i = 0, j = avp.size(); i < j; i++)
2195 afs[i] = (AlignFrame) avp.elementAt(i);
2200 public AppJmol[] getJmols()
2202 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2208 Vector avp = new Vector();
2212 for (int i = frames.length - 1; i > -1; i--)
2214 if (frames[i] instanceof AppJmol)
2216 AppJmol af = (AppJmol) frames[i];
2220 } catch (Exception ex)
2222 ex.printStackTrace();
2224 if (avp.size() == 0)
2228 AppJmol afs[] = new AppJmol[avp.size()];
2229 for (int i = 0, j = avp.size(); i < j; i++)
2231 afs[i] = (AppJmol) avp.elementAt(i);
2238 * Add Groovy Support to Jalview
2240 public void groovyShell_actionPerformed(ActionEvent e)
2242 // use reflection to avoid creating compilation dependency.
2243 if (!jalview.bin.Cache.groovyJarsPresent())
2246 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2250 Class gcClass = Desktop.class.getClassLoader().loadClass(
2251 "groovy.ui.Console");
2252 Constructor gccons = gcClass.getConstructor(null);
2253 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2255 { String.class, Object.class });
2256 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2257 Object gc = gccons.newInstance(null);
2258 setvar.invoke(gc, new Object[]
2259 { "Jalview", this });
2260 run.invoke(gc, null);
2261 } catch (Exception ex)
2263 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2265 .showInternalMessageDialog(
2268 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2269 "Jalview Groovy Support Failed",
2270 JOptionPane.ERROR_MESSAGE);
2275 * Progress bars managed by the IProgressIndicator method.
2277 private Hashtable<Long,JPanel> progressBars;
2278 private Hashtable<Long,IProgressIndicatorHandler> progressBarHandlers;
2283 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2285 public void setProgressBar(String message, long id)
2287 if (progressBars == null)
2289 progressBars = new Hashtable<Long,JPanel>();
2290 progressBarHandlers = new Hashtable<Long,IProgressIndicatorHandler>();
2293 if (progressBars.get(new Long(id)) != null)
2295 JPanel progressPanel = progressBars
2296 .remove(new Long(id));
2297 if (progressBarHandlers.contains(new Long(id)))
2299 progressBarHandlers.remove(new Long(id));
2301 removeProgressPanel(progressPanel);
2305 progressBars.put(new Long(id), addProgressPanel(message));
2312 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2313 * jalview.gui.IProgressIndicatorHandler)
2315 public void registerHandler(final long id,
2316 final IProgressIndicatorHandler handler)
2318 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2321 "call setProgressBar before registering the progress bar's handler.");
2323 progressBarHandlers.put(new Long(id), handler);
2324 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2325 if (handler.canCancel())
2327 JButton cancel = new JButton("Cancel");
2328 final IProgressIndicator us = this;
2329 cancel.addActionListener(new ActionListener()
2332 public void actionPerformed(ActionEvent e)
2334 handler.cancelActivity(id);
2337 + ((JLabel) progressPanel.getComponent(0))
2341 progressPanel.add(cancel, BorderLayout.EAST);
2347 * @return true if any progress bars are still active
2350 public boolean operationInProgress()
2352 if (progressBars != null && progressBars.size() > 0)
2360 * This will return the first AlignFrame viewing AlignViewport av. It will
2361 * break if there are more than one AlignFrames viewing a particular av. This
2364 * @return alignFrame for av
2366 public static AlignFrame getAlignFrameFor(AlignViewport av)
2368 if (desktop != null)
2370 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2371 for (int panel = 0; aps != null && panel < aps.length; panel++)
2373 if (aps[panel] != null && aps[panel].av == av)
2375 return aps[panel].alignFrame;
2382 public VamsasApplication getVamsasApplication()
2389 * flag set if jalview GUI is being operated programmatically
2391 private boolean inBatchMode = false;
2394 * check if jalview GUI is being operated programmatically
2396 * @return inBatchMode
2398 public boolean isInBatchMode()
2404 * set flag if jalview GUI is being operated programmatically
2406 * @param inBatchMode
2408 public void setInBatchMode(boolean inBatchMode)
2410 this.inBatchMode = inBatchMode;
2413 public void startServiceDiscovery()
2415 startServiceDiscovery(false);
2418 public void startServiceDiscovery(boolean blocking)
2420 boolean alive = true;
2421 Thread t0 = null, t1 = null, t2 = null;
2423 // todo: changesupport handlers need to be transferred
2424 if (discoverer == null)
2426 discoverer = new jalview.ws.jws1.Discoverer();
2427 // register PCS handler for desktop.
2428 discoverer.addPropertyChangeListener(changeSupport);
2430 // JAL-940 - disabled JWS1 service configuration - always start discoverer until we phase out completely
2433 (t0 = new Thread(discoverer)).start();
2438 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2440 // EnfinEnvision web service menu entries are rebuild every time the
2441 // menu is shown, so no changeSupport events are needed.
2442 jalview.ws.EnfinEnvision2OneWay.getInstance();
2443 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2446 } catch (Exception e)
2449 .info("Exception when trying to launch Envision2 workflow discovery.",
2451 Cache.log.info(e.getStackTrace());
2453 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2455 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2457 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2459 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2465 // TODO: do rest service discovery
2474 } catch (Exception e)
2477 alive = (t1 != null && t1.isAlive())
2478 || (t2 != null && t2.isAlive())
2479 || (t3 != null && t3.isAlive())
2480 || (t0 != null && t0.isAlive());
2486 * called to check if the service discovery process completed successfully.
2490 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2492 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2494 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2495 .getErrorMessages();
2498 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2500 if (serviceChangedDialog == null)
2502 // only run if we aren't already displaying one of these.
2503 addDialogThread(serviceChangedDialog = new Runnable()
2509 JalviewDialog jd =new JalviewDialog() {
2511 protected void cancelPressed()
2513 // TODO Auto-generated method stub
2516 protected void okPressed()
2518 // TODO Auto-generated method stub
2521 protected void raiseClosed()
2523 // TODO Auto-generated method stub
2527 jd.initDialogFrame(new JLabel("<html><table width=\"450\"><tr><td>"
2529 + "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2530 + " or mis-configured HTTP proxy settings.<br/>"
2531 + "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2532 + " Tools->Preferences dialog box to change them.</td></tr></table></html>"), true, true, "Web Service Configuration Problem", 450, 400);
2536 JOptionPane.showConfirmDialog(
2538 new JLabel("<html><table width=\"450\"><tr><td>"
2539 + ermsg+"</td></tr></table>"
2540 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2541 + " or mis-configured HTTP proxy settings.</p>"
2542 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2543 + " Tools->Preferences dialog box to change them.</p></html>"), "Web Service Configuration Problem",
2544 JOptionPane.DEFAULT_OPTION,
2545 JOptionPane.ERROR_MESSAGE);
2546 serviceChangedDialog = null;
2555 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2562 private Runnable serviceChangedDialog = null;
2565 * start a thread to open a URL in the configured browser. Pops up a warning
2566 * dialog to the user if there is an exception when calling out to the browser
2571 public static void showUrl(final String url)
2573 showUrl(url, Desktop.instance);
2576 * Like showUrl but allows progress handler to be specified
2578 * @param progress (null) or object implementing IProgressIndicator
2580 public static void showUrl(final String url, final IProgressIndicator progress)
2582 new Thread(new Runnable()
2588 if (progress!=null) {
2589 progress.setProgressBar("Opening "+url, this.hashCode());
2591 jalview.util.BrowserLauncher.openURL(url);
2592 } catch (Exception ex)
2595 .showInternalMessageDialog(
2597 "Unixers: Couldn't find default web browser."
2598 + "\nAdd the full path to your browser in Preferences.",
2599 "Web browser not found",
2600 JOptionPane.WARNING_MESSAGE);
2602 ex.printStackTrace();
2604 if (progress!=null) {
2605 progress.setProgressBar(null, this.hashCode());
2611 public static WsParamSetManager wsparamManager = null;
2613 public static ParamManager getUserParameterStore()
2615 if (wsparamManager == null)
2617 wsparamManager = new WsParamSetManager();
2619 return wsparamManager;
2623 * static hyperlink handler proxy method for use by Jalview's internal windows
2626 public static void hyperlinkUpdate(HyperlinkEvent e)
2628 if (e.getEventType() == EventType.ACTIVATED)
2633 url = e.getURL().toString();
2634 Desktop.showUrl(url);
2635 } catch (Exception x)
2638 if (Cache.log!=null) {
2639 Cache.log.error("Couldn't handle string "+url+" as a URL.");
2641 System.err.println("Couldn't handle string "+url+" as a URL.");
2644 // ignore any exceptions due to dud links.
2650 * single thread that handles display of dialogs to user.
2652 ExecutorService dialogExecutor=Executors.newSingleThreadExecutor();
2654 * flag indicating if dialogExecutor should try to acquire a permit
2656 private volatile boolean dialogPause=true;
2660 private java.util.concurrent.Semaphore block=new Semaphore(0);
2663 * add another dialog thread to the queue
2666 public void addDialogThread(final Runnable prompter)
2668 dialogExecutor.submit(new Runnable()
2673 try { block.acquire(); } catch (InterruptedException x){};
2681 SwingUtilities.invokeAndWait(prompter);
2682 } catch (Exception q)
2684 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2690 public void startDialogQueue()
2692 // set the flag so we don't pause waiting for another permit and semaphore the current task to begin