2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
21 import jalview.io.FileLoader;
22 import jalview.io.FormatAdapter;
23 import jalview.io.IdentifyFile;
24 import jalview.io.JalviewFileChooser;
25 import jalview.io.JalviewFileView;
26 import jalview.ws.params.ParamManager;
28 import java.awt.BorderLayout;
29 import java.awt.Color;
30 import java.awt.Dimension;
31 import java.awt.FontMetrics;
32 import java.awt.Graphics;
33 import java.awt.GridLayout;
34 import java.awt.Point;
35 import java.awt.Rectangle;
36 import java.awt.Toolkit;
37 import java.awt.datatransfer.Clipboard;
38 import java.awt.datatransfer.ClipboardOwner;
39 import java.awt.datatransfer.DataFlavor;
40 import java.awt.datatransfer.Transferable;
41 import java.awt.dnd.DnDConstants;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetEvent;
45 import java.awt.dnd.DropTargetListener;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.awt.event.MouseAdapter;
51 import java.awt.event.MouseEvent;
52 import java.awt.event.MouseListener;
53 import java.awt.event.WindowAdapter;
54 import java.awt.event.WindowEvent;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.beans.PropertyVetoException;
58 import java.io.BufferedInputStream;
60 import java.io.FileOutputStream;
61 import java.lang.reflect.Constructor;
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,
102 jalview.api.StructureSelectionManagerProvider
105 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
108 * news reader - null if it was never started.
110 private BlogReader jvnews = null;
114 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
116 public void addJalviewPropertyChangeListener(
117 PropertyChangeListener listener)
119 changeSupport.addJalviewPropertyChangeListener(listener);
123 * @param propertyName
125 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
126 * java.beans.PropertyChangeListener)
128 public void addJalviewPropertyChangeListener(String propertyName,
129 PropertyChangeListener listener)
131 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
135 * @param propertyName
137 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
138 * java.beans.PropertyChangeListener)
140 public void removeJalviewPropertyChangeListener(String propertyName,
141 PropertyChangeListener listener)
143 changeSupport.removeJalviewPropertyChangeListener(propertyName,
147 /** Singleton Desktop instance */
148 public static Desktop instance;
150 public static MyDesktopPane desktop;
152 static int openFrameCount = 0;
154 static final int xOffset = 30;
156 static final int yOffset = 30;
158 public static jalview.ws.jws1.Discoverer discoverer;
160 public static Object[] jalviewClipboard;
162 public static boolean internalCopy = false;
164 static int fileLoadingCount = 0;
166 class MyDesktopManager implements DesktopManager
169 private DesktopManager delegate;
171 public MyDesktopManager(DesktopManager delegate)
173 this.delegate = delegate;
176 public void activateFrame(JInternalFrame f)
180 delegate.activateFrame(f);
181 } catch (NullPointerException npe)
183 Point p = getMousePosition();
184 instance.showPasteMenu(p.x, p.y);
188 public void beginDraggingFrame(JComponent f)
190 delegate.beginDraggingFrame(f);
193 public void beginResizingFrame(JComponent f, int direction)
195 delegate.beginResizingFrame(f, direction);
198 public void closeFrame(JInternalFrame f)
200 delegate.closeFrame(f);
203 public void deactivateFrame(JInternalFrame f)
205 delegate.deactivateFrame(f);
208 public void deiconifyFrame(JInternalFrame f)
210 delegate.deiconifyFrame(f);
213 public void dragFrame(JComponent f, int newX, int newY)
219 delegate.dragFrame(f, newX, newY);
222 public void endDraggingFrame(JComponent f)
224 delegate.endDraggingFrame(f);
227 public void endResizingFrame(JComponent f)
229 delegate.endResizingFrame(f);
232 public void iconifyFrame(JInternalFrame f)
234 delegate.iconifyFrame(f);
237 public void maximizeFrame(JInternalFrame f)
239 delegate.maximizeFrame(f);
242 public void minimizeFrame(JInternalFrame f)
244 delegate.minimizeFrame(f);
247 public void openFrame(JInternalFrame f)
249 delegate.openFrame(f);
252 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
255 Rectangle b = desktop.getBounds();
260 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
263 public void setBoundsForFrame(JComponent f, int newX, int newY,
264 int newWidth, int newHeight)
266 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
269 // All other methods, simply delegate
274 * Creates a new Desktop object.
279 * A note to implementors. It is ESSENTIAL that any activities that might
280 * block are spawned off as threads rather than waited for during this
284 doVamsasClientCheck();
287 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
288 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
289 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
291 boolean showjconsole = jalview.bin.Cache.getDefault(
292 "SHOW_JAVA_CONSOLE", false);
293 desktop = new MyDesktopPane(selmemusage);
294 showMemusage.setSelected(selmemusage);
295 desktop.setBackground(Color.white);
296 getContentPane().setLayout(new BorderLayout());
297 // alternate config - have scrollbars - see notes in JAL-153
298 // JScrollPane sp = new JScrollPane();
299 // sp.getViewport().setView(desktop);
300 // getContentPane().add(sp, BorderLayout.CENTER);
301 getContentPane().add(desktop, BorderLayout.CENTER);
302 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()
425 Cache.log.debug("Starting news thread.");
427 jvnews = new BlogReader(me);
428 showNews.setVisible(true);
429 Cache.log.debug("Completed news thread.");
434 protected void showNews_actionPerformed(ActionEvent e)
436 showNews(showNews.isSelected());
439 void showNews(boolean visible)
442 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
443 showNews.setSelected(visible);
444 if (visible && !jvnews.isVisible())
446 new Thread(new Runnable()
451 long instance = System.currentTimeMillis();
452 Desktop.instance.setProgressBar("Refreshing news", instance);
453 jvnews.refreshNews();
454 Desktop.instance.setProgressBar(null, instance);
463 * recover the last known dimensions for a jalview window
466 * - empty string is desktop, all other windows have unique prefix
467 * @return null or last known dimensions scaled to current geometry (if last
468 * window geom was known)
470 Rectangle getLastKnownDimensions(String windowName)
472 // TODO: lock aspect ratio for scaling desktop Bug #0058199
473 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
474 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
475 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
476 String width = jalview.bin.Cache.getProperty(windowName
478 String height = jalview.bin.Cache.getProperty(windowName
480 if ((x != null) && (y != null) && (width != null) && (height != null))
482 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
483 .parseInt(width), ih = Integer.parseInt(height);
484 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
486 // attempt #1 - try to cope with change in screen geometry - this
487 // version doesn't preserve original jv aspect ratio.
488 // take ratio of current screen size vs original screen size.
489 double sw = ((1f * screenSize.width) / (1f * Integer
490 .parseInt(jalview.bin.Cache
491 .getProperty("SCREENGEOMETRY_WIDTH"))));
492 double sh = ((1f * screenSize.height) / (1f * Integer
493 .parseInt(jalview.bin.Cache
494 .getProperty("SCREENGEOMETRY_HEIGHT"))));
495 // rescale the bounds depending upon the current screen geometry.
496 ix = (int) (ix * sw);
497 iw = (int) (iw * sw);
498 iy = (int) (iy * sh);
499 ih = (int) (ih * sh);
500 while (ix >= screenSize.width)
502 jalview.bin.Cache.log
503 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
504 ix -= screenSize.width;
506 while (iy >= screenSize.height)
508 jalview.bin.Cache.log
509 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
510 iy -= screenSize.height;
512 jalview.bin.Cache.log.debug("Got last known dimensions for "
513 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
516 // return dimensions for new instance
517 return new Rectangle(ix, iy, iw, ih);
522 private void doVamsasClientCheck()
524 if (jalview.bin.Cache.vamsasJarsPresent())
526 setupVamsasDisconnectedGui();
527 VamsasMenu.setVisible(true);
528 final Desktop us = this;
529 VamsasMenu.addMenuListener(new MenuListener()
531 // this listener remembers when the menu was first selected, and
532 // doesn't rebuild the session list until it has been cleared and
534 boolean refresh = true;
536 public void menuCanceled(MenuEvent e)
541 public void menuDeselected(MenuEvent e)
546 public void menuSelected(MenuEvent e)
550 us.buildVamsasStMenu();
555 vamsasStart.setVisible(true);
559 void showPasteMenu(int x, int y)
561 JPopupMenu popup = new JPopupMenu();
562 JMenuItem item = new JMenuItem("Paste To New Window");
563 item.addActionListener(new ActionListener()
565 public void actionPerformed(ActionEvent evt)
572 popup.show(this, x, y);
579 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
580 Transferable contents = c.getContents(this);
582 if (contents != null)
584 String file = (String) contents
585 .getTransferData(DataFlavor.stringFlavor);
587 String format = new IdentifyFile().Identify(file,
588 FormatAdapter.PASTE);
590 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
593 } catch (Exception ex)
596 .println("Unable to paste alignment from system clipboard:\n"
602 * Adds and opens the given frame to the desktop
613 public static synchronized void addInternalFrame(
614 final JInternalFrame frame, String title, int w, int h)
616 addInternalFrame(frame, title, w, h, true);
633 public static synchronized void addInternalFrame(
634 final JInternalFrame frame, String title, int w, int h,
638 // TODO: allow callers to determine X and Y position of frame (eg. via
640 // TODO: consider fixing method to update entries in the window submenu with
641 // the current window title
643 frame.setTitle(title);
644 if (frame.getWidth() < 1 || frame.getHeight() < 1)
648 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
649 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
650 // IF JALVIEW IS RUNNING HEADLESS
651 // ///////////////////////////////////////////////
652 if (System.getProperty("java.awt.headless") != null
653 && System.getProperty("java.awt.headless").equals("true"))
660 frame.setVisible(true);
661 frame.setClosable(true);
662 frame.setResizable(resizable);
663 frame.setMaximizable(resizable);
664 frame.setIconifiable(resizable);
665 frame.setFrameIcon(null);
667 if (frame.getX() < 1 && frame.getY() < 1)
669 frame.setLocation(xOffset * openFrameCount, yOffset
670 * ((openFrameCount - 1) % 10) + yOffset);
673 final JMenuItem menuItem = new JMenuItem(title);
674 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
676 public void internalFrameActivated(
677 javax.swing.event.InternalFrameEvent evt)
679 JInternalFrame itf = desktop.getSelectedFrame();
687 public void internalFrameClosed(
688 javax.swing.event.InternalFrameEvent evt)
690 PaintRefresher.RemoveComponent(frame);
692 windowMenu.remove(menuItem);
693 JInternalFrame itf = desktop.getSelectedFrame();
702 menuItem.addActionListener(new ActionListener()
704 public void actionPerformed(ActionEvent e)
708 frame.setSelected(true);
709 frame.setIcon(false);
710 } catch (java.beans.PropertyVetoException ex)
716 menuItem.addMouseListener(new MouseListener()
720 public void mouseReleased(MouseEvent e)
725 public void mousePressed(MouseEvent e)
730 public void mouseExited(MouseEvent e)
734 frame.setSelected(false);
735 } catch (PropertyVetoException e1)
741 public void mouseEntered(MouseEvent e)
745 frame.setSelected(true);
746 } catch (PropertyVetoException e1)
752 public void mouseClicked(MouseEvent e)
758 windowMenu.add(menuItem);
764 frame.setSelected(true);
765 frame.requestFocus();
766 } catch (java.beans.PropertyVetoException ve)
768 } catch (java.lang.ClassCastException cex)
771 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
776 public void lostOwnership(Clipboard clipboard, Transferable contents)
780 Desktop.jalviewClipboard = null;
783 internalCopy = false;
786 public void dragEnter(DropTargetDragEvent evt)
790 public void dragExit(DropTargetEvent evt)
794 public void dragOver(DropTargetDragEvent evt)
798 public void dropActionChanged(DropTargetDragEvent evt)
808 public void drop(DropTargetDropEvent evt)
810 Transferable t = evt.getTransferable();
811 java.util.List files = null;
812 java.util.List protocols = null;
816 DataFlavor uriListFlavor = new DataFlavor(
817 "text/uri-list;class=java.lang.String");
818 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
820 // Works on Windows and MacOSX
821 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
822 files = (java.util.List) t
823 .getTransferData(DataFlavor.javaFileListFlavor);
825 else if (t.isDataFlavorSupported(uriListFlavor))
827 // This is used by Unix drag system
828 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
829 String data = (String) t.getTransferData(uriListFlavor);
830 files = new java.util.ArrayList(1);
831 protocols = new java.util.ArrayList(1);
832 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
833 data, "\r\n"); st.hasMoreTokens();)
835 String s = st.nextToken();
836 if (s.startsWith("#"))
838 // the line is a comment (as per the RFC 2483)
841 java.net.URI uri = new java.net.URI(s);
842 if (uri.getScheme().toLowerCase().startsWith("http"))
844 protocols.add(FormatAdapter.URL);
845 files.add(uri.toString());
849 // otherwise preserve old behaviour: catch all for file objects
850 java.io.File file = new java.io.File(uri);
851 protocols.add(FormatAdapter.FILE);
852 files.add(file.toString());
856 } catch (Exception e)
864 for (int i = 0; i < files.size(); i++)
866 String file = files.get(i).toString();
867 String protocol = (protocols == null) ? FormatAdapter.FILE
868 : (String) protocols.get(i);
869 String format = null;
871 if (file.endsWith(".jar"))
878 format = new IdentifyFile().Identify(file, protocol);
881 new FileLoader().LoadFile(file, protocol, format);
884 } catch (Exception ex)
896 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
898 JalviewFileChooser chooser = new JalviewFileChooser(
899 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
900 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
901 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
902 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
904 chooser.setFileView(new JalviewFileView());
905 chooser.setDialogTitle("Open local file");
906 chooser.setToolTipText("Open");
908 int value = chooser.showOpenDialog(this);
910 if (value == JalviewFileChooser.APPROVE_OPTION)
912 String choice = chooser.getSelectedFile().getPath();
913 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
914 .getSelectedFile().getParent());
916 String format = null;
917 if (chooser.getSelectedFormat().equals("Jalview"))
923 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
926 if (viewport != null)
928 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
933 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
944 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
946 // This construct allows us to have a wider textfield
948 JLabel label = new JLabel("Enter URL of Input File");
949 final JComboBox history = new JComboBox();
951 JPanel panel = new JPanel(new GridLayout(2, 1));
954 history.setPreferredSize(new Dimension(400, 20));
955 history.setEditable(true);
956 history.addItem("http://www.");
958 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
962 if (historyItems != null)
964 st = new StringTokenizer(historyItems, "\t");
966 while (st.hasMoreTokens())
968 history.addItem(st.nextElement());
972 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
973 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
975 if (reply != JOptionPane.OK_OPTION)
980 String url = history.getSelectedItem().toString();
982 if (url.toLowerCase().endsWith(".jar"))
984 if (viewport != null)
986 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
991 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
996 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
998 if (format.equals("URL NOT FOUND"))
1000 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1001 "Couldn't locate " + url, "URL not found",
1002 JOptionPane.WARNING_MESSAGE);
1007 if (viewport != null)
1009 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1013 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1024 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1026 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1027 cap.setForInput(viewport);
1028 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1036 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1038 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1039 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1041 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1042 getBounds().y, getWidth(), getHeight()));
1044 if (jconsole != null)
1046 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1047 jconsole.stopConsole();
1051 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1054 if (dialogExecutor != null)
1056 dialogExecutor.shutdownNow();
1062 private void storeLastKnownDimensions(String string, Rectangle jc)
1064 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1065 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1066 + " height:" + jc.height);
1068 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1069 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1070 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1071 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1080 public void aboutMenuItem_actionPerformed(ActionEvent e)
1082 // StringBuffer message = getAboutMessage(false);
1083 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1085 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1086 new Thread(new Runnable()
1090 new SplashScreen(true);
1095 public StringBuffer getAboutMessage(boolean shortv)
1097 StringBuffer message = new StringBuffer();
1098 message.append("<html>");
1101 message.append("<h1><strong>Version: "
1102 + jalview.bin.Cache.getProperty("VERSION")
1103 + "</strong></h1><br>");
1104 message.append("<strong>Last Updated: <em>"
1105 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1106 + "</em></strong>");
1112 message.append("<strong>Version "
1113 + jalview.bin.Cache.getProperty("VERSION")
1114 + "; last updated: "
1115 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1118 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1121 message.append("<br>...Checking latest version...</br>");
1123 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1124 .equals(jalview.bin.Cache.getProperty("VERSION")))
1126 boolean red = false;
1127 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1128 .indexOf("automated build") == -1)
1131 // Displayed when code version and jnlp version do not match and code
1132 // version is not a development build
1133 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1136 message.append("<br>!! Version "
1137 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1139 + " is available for download from "
1140 + jalview.bin.Cache.getDefault("www.jalview.org",
1141 "http://www.jalview.org") + " !!");
1144 message.append("</div>");
1147 message.append("<br>Authors: "
1151 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1152 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1153 + "<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"
1154 + "<br>If you use Jalview, please cite:"
1155 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1156 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1157 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1168 public void documentationMenuItem_actionPerformed(ActionEvent e)
1172 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1173 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1174 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1176 javax.help.HelpBroker hb = hs.createHelpBroker();
1177 hb.setCurrentID("home");
1178 hb.setDisplayed(true);
1179 } catch (Exception ex)
1184 public void closeAll_actionPerformed(ActionEvent e)
1186 JInternalFrame[] frames = desktop.getAllFrames();
1187 for (int i = 0; i < frames.length; i++)
1191 frames[i].setClosed(true);
1192 } catch (java.beans.PropertyVetoException ex)
1196 System.out.println("ALL CLOSED");
1197 if (v_client != null)
1199 // TODO clear binding to vamsas document objects on close_all
1204 public void raiseRelated_actionPerformed(ActionEvent e)
1206 reorderAssociatedWindows(false, false);
1209 public void minimizeAssociated_actionPerformed(ActionEvent e)
1211 reorderAssociatedWindows(true, false);
1214 void closeAssociatedWindows()
1216 reorderAssociatedWindows(false, true);
1222 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1225 protected void garbageCollect_actionPerformed(ActionEvent e)
1227 // We simply collect the garbage
1228 jalview.bin.Cache.log.debug("Collecting garbage...");
1230 jalview.bin.Cache.log.debug("Finished garbage collection.");
1237 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1240 protected void showMemusage_actionPerformed(ActionEvent e)
1242 desktop.showMemoryUsage(showMemusage.isSelected());
1249 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1252 protected void showConsole_actionPerformed(ActionEvent e)
1254 showConsole(showConsole.isSelected());
1257 Console jconsole = null;
1260 * control whether the java console is visible or not
1264 void showConsole(boolean selected)
1266 showConsole.setSelected(selected);
1267 // TODO: decide if we should update properties file
1268 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1270 jconsole.setVisible(selected);
1273 void reorderAssociatedWindows(boolean minimize, boolean close)
1275 JInternalFrame[] frames = desktop.getAllFrames();
1276 if (frames == null || frames.length < 1)
1281 AlignViewport source = null, target = null;
1282 if (frames[0] instanceof AlignFrame)
1284 source = ((AlignFrame) frames[0]).getCurrentView();
1286 else if (frames[0] instanceof TreePanel)
1288 source = ((TreePanel) frames[0]).getViewPort();
1290 else if (frames[0] instanceof PCAPanel)
1292 source = ((PCAPanel) frames[0]).av;
1294 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1296 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1301 for (int i = 0; i < frames.length; i++)
1304 if (frames[i] == null)
1308 if (frames[i] instanceof AlignFrame)
1310 target = ((AlignFrame) frames[i]).getCurrentView();
1312 else if (frames[i] instanceof TreePanel)
1314 target = ((TreePanel) frames[i]).getViewPort();
1316 else if (frames[i] instanceof PCAPanel)
1318 target = ((PCAPanel) frames[i]).av;
1320 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1322 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1325 if (source == target)
1331 frames[i].setClosed(true);
1335 frames[i].setIcon(minimize);
1338 frames[i].toFront();
1342 } catch (java.beans.PropertyVetoException ex)
1356 protected void preferences_actionPerformed(ActionEvent e)
1367 public void saveState_actionPerformed(ActionEvent e)
1369 JalviewFileChooser chooser = new JalviewFileChooser(
1370 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1371 { "jar" }, new String[]
1372 { "Jalview Project" }, "Jalview Project");
1374 chooser.setFileView(new JalviewFileView());
1375 chooser.setDialogTitle("Save State");
1377 int value = chooser.showSaveDialog(this);
1379 if (value == JalviewFileChooser.APPROVE_OPTION)
1381 final Desktop me = this;
1382 final java.io.File choice = chooser.getSelectedFile();
1383 new Thread(new Runnable()
1388 setProgressBar("Saving jalview project " + choice.getName(),
1390 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1391 choice.getParent());
1392 // TODO catch and handle errors for savestate
1393 // TODO prevent user from messing with the Desktop whilst we're saving
1396 new Jalview2XML().SaveState(choice);
1397 } catch (OutOfMemoryError oom)
1399 new OOMWarning("Whilst saving current state to "
1400 + choice.getName(), oom);
1401 } catch (Exception ex)
1404 "Problems whilst trying to save to " + choice.getName(),
1406 JOptionPane.showMessageDialog(
1408 "Error whilst saving current state to "
1409 + choice.getName(), "Couldn't save project",
1410 JOptionPane.WARNING_MESSAGE);
1412 setProgressBar(null, choice.hashCode());
1424 public void loadState_actionPerformed(ActionEvent e)
1426 JalviewFileChooser chooser = new JalviewFileChooser(
1427 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1428 { "jar" }, new String[]
1429 { "Jalview Project" }, "Jalview Project");
1430 chooser.setFileView(new JalviewFileView());
1431 chooser.setDialogTitle("Restore state");
1433 int value = chooser.showOpenDialog(this);
1435 if (value == JalviewFileChooser.APPROVE_OPTION)
1437 final String choice = chooser.getSelectedFile().getAbsolutePath();
1438 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1439 .getSelectedFile().getParent());
1440 new Thread(new Runnable()
1444 setProgressBar("loading jalview project " + choice,
1448 new Jalview2XML().LoadJalviewAlign(choice);
1449 } catch (OutOfMemoryError oom)
1451 new OOMWarning("Whilst loading project from " + choice, oom);
1452 } catch (Exception ex)
1454 Cache.log.error("Problems whilst loading project from "
1456 JOptionPane.showMessageDialog(Desktop.desktop,
1457 "Error whilst loading project from " + choice,
1458 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1460 setProgressBar(null, choice.hashCode());
1466 public void inputSequence_actionPerformed(ActionEvent e)
1468 new SequenceFetcher(this);
1471 JPanel progressPanel;
1473 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1475 public void startLoading(final String fileName)
1477 if (fileLoadingCount == 0)
1479 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1485 private JPanel addProgressPanel(String string)
1487 if (progressPanel == null)
1489 progressPanel = new JPanel(new GridLayout(1, 1));
1490 totalProgressCount = 0;
1491 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1493 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1494 JProgressBar progressBar = new JProgressBar();
1495 progressBar.setIndeterminate(true);
1497 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1499 thisprogress.add(progressBar, BorderLayout.CENTER);
1500 progressPanel.add(thisprogress);
1501 ((GridLayout) progressPanel.getLayout())
1502 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1503 ++totalProgressCount;
1504 instance.validate();
1505 return thisprogress;
1508 int totalProgressCount = 0;
1510 private void removeProgressPanel(JPanel progbar)
1512 if (progressPanel != null)
1514 progressPanel.remove(progbar);
1515 GridLayout gl = (GridLayout) progressPanel.getLayout();
1516 gl.setRows(gl.getRows() - 1);
1517 if (--totalProgressCount < 1)
1519 this.getContentPane().remove(progressPanel);
1520 progressPanel = null;
1526 public void stopLoading()
1529 if (fileLoadingCount < 1)
1531 for (JPanel flp : fileLoadingPanels)
1533 removeProgressPanel(flp);
1535 fileLoadingPanels.clear();
1536 fileLoadingCount = 0;
1541 public static int getViewCount(String alignmentId)
1543 AlignViewport[] aps = getViewports(alignmentId);
1544 return (aps == null) ? 0 : aps.length;
1549 * @param alignmentId
1550 * @return all AlignmentPanels concerning the alignmentId sequence set
1552 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1555 if (Desktop.desktop == null)
1557 // no frames created and in headless mode
1558 // TODO: verify that frames are recoverable when in headless mode
1561 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1562 ArrayList aps = new ArrayList();
1563 for (int t = 0; t < frames.length; t++)
1565 if (frames[t] instanceof AlignFrame)
1567 AlignFrame af = (AlignFrame) frames[t];
1568 for (int a = 0; a < af.alignPanels.size(); a++)
1570 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1571 .elementAt(a)).av.getSequenceSetId()))
1573 aps.add(af.alignPanels.elementAt(a));
1578 if (aps.size() == 0)
1582 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1583 for (int t = 0; t < vap.length; t++)
1585 vap[t] = (AlignmentPanel) aps.get(t);
1591 * get all the viewports on an alignment.
1593 * @param sequenceSetId
1594 * unique alignment id
1595 * @return all viewports on the alignment bound to sequenceSetId
1597 public static AlignViewport[] getViewports(String sequenceSetId)
1599 Vector viewp = new Vector();
1600 if (desktop != null)
1602 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1604 for (int t = 0; t < frames.length; t++)
1606 if (frames[t] instanceof AlignFrame)
1608 AlignFrame afr = ((AlignFrame) frames[t]);
1609 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1611 if (afr.alignPanels != null)
1613 for (int a = 0; a < afr.alignPanels.size(); a++)
1615 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1616 .elementAt(a)).av.getSequenceSetId()))
1618 viewp.addElement(((AlignmentPanel) afr.alignPanels
1625 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1630 if (viewp.size() > 0)
1632 AlignViewport[] vp = new AlignViewport[viewp.size()];
1640 public void explodeViews(AlignFrame af)
1642 int size = af.alignPanels.size();
1648 for (int i = 0; i < size; i++)
1650 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1651 AlignFrame newaf = new AlignFrame(ap);
1652 if (ap.av.explodedPosition != null
1653 && !ap.av.explodedPosition.equals(af.getBounds()))
1655 newaf.setBounds(ap.av.explodedPosition);
1658 ap.av.gatherViewsHere = false;
1660 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1661 AlignFrame.DEFAULT_HEIGHT);
1664 af.alignPanels.clear();
1665 af.closeMenuItem_actionPerformed(true);
1669 public void gatherViews(AlignFrame source)
1671 source.viewport.gatherViewsHere = true;
1672 source.viewport.explodedPosition = source.getBounds();
1673 JInternalFrame[] frames = desktop.getAllFrames();
1674 String viewId = source.viewport.getSequenceSetId();
1676 for (int t = 0; t < frames.length; t++)
1678 if (frames[t] instanceof AlignFrame && frames[t] != source)
1680 AlignFrame af = (AlignFrame) frames[t];
1681 boolean gatherThis = false;
1682 for (int a = 0; a < af.alignPanels.size(); a++)
1684 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1685 if (viewId.equals(ap.av.getSequenceSetId()))
1688 ap.av.gatherViewsHere = false;
1689 ap.av.explodedPosition = af.getBounds();
1690 source.addAlignmentPanel(ap, false);
1696 af.alignPanels.clear();
1697 af.closeMenuItem_actionPerformed(true);
1704 jalview.gui.VamsasApplication v_client = null;
1706 public void vamsasImport_actionPerformed(ActionEvent e)
1708 if (v_client == null)
1710 // Load and try to start a session.
1711 JalviewFileChooser chooser = new JalviewFileChooser(
1712 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1714 chooser.setFileView(new JalviewFileView());
1715 chooser.setDialogTitle("Open a saved VAMSAS session");
1716 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1718 int value = chooser.showOpenDialog(this);
1720 if (value == JalviewFileChooser.APPROVE_OPTION)
1722 String fle = chooser.getSelectedFile().toString();
1723 if (!vamsasImport(chooser.getSelectedFile()))
1725 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1726 "Couldn't import '" + fle + "' as a new vamsas session.",
1727 "Vamsas Document Import Failed",
1728 JOptionPane.ERROR_MESSAGE);
1734 jalview.bin.Cache.log
1735 .error("Implementation error - load session from a running session is not supported.");
1740 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1743 * @return true if import was a success and a session was started.
1745 public boolean vamsasImport(URL url)
1747 // TODO: create progress bar
1748 if (v_client != null)
1751 jalview.bin.Cache.log
1752 .error("Implementation error - load session from a running session is not supported.");
1758 // copy the URL content to a temporary local file
1759 // TODO: be a bit cleverer here with nio (?!)
1760 File file = File.createTempFile("vdocfromurl", ".vdj");
1761 FileOutputStream fos = new FileOutputStream(file);
1762 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1763 byte[] buffer = new byte[2048];
1765 while ((ln = bis.read(buffer)) > -1)
1767 fos.write(buffer, 0, ln);
1771 v_client = new jalview.gui.VamsasApplication(this, file,
1772 url.toExternalForm());
1773 } catch (Exception ex)
1775 jalview.bin.Cache.log.error(
1776 "Failed to create new vamsas session from contents of URL "
1780 setupVamsasConnectedGui();
1781 v_client.initial_update(); // TODO: thread ?
1782 return v_client.inSession();
1786 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1789 * @return true if import was a success and a session was started.
1791 public boolean vamsasImport(File file)
1793 if (v_client != null)
1796 jalview.bin.Cache.log
1797 .error("Implementation error - load session from a running session is not supported.");
1801 setProgressBar("Importing VAMSAS session from " + file.getName(),
1805 v_client = new jalview.gui.VamsasApplication(this, file, null);
1806 } catch (Exception ex)
1808 setProgressBar("Importing VAMSAS session from " + file.getName(),
1810 jalview.bin.Cache.log.error(
1811 "New vamsas session from existing session file failed:", ex);
1814 setupVamsasConnectedGui();
1815 v_client.initial_update(); // TODO: thread ?
1816 setProgressBar("Importing VAMSAS session from " + file.getName(),
1818 return v_client.inSession();
1821 public boolean joinVamsasSession(String mysesid)
1823 if (v_client != null)
1826 "Trying to join a vamsas session when another is already connected.");
1828 if (mysesid == null)
1830 throw new Error("Invalid vamsas session id.");
1832 v_client = new VamsasApplication(this, mysesid);
1833 setupVamsasConnectedGui();
1834 v_client.initial_update();
1835 return (v_client.inSession());
1838 public void vamsasStart_actionPerformed(ActionEvent e)
1840 if (v_client == null)
1843 // we just start a default session for moment.
1845 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1846 * getProperty("LAST_DIRECTORY"));
1848 * chooser.setFileView(new JalviewFileView());
1849 * chooser.setDialogTitle("Load Vamsas file");
1850 * chooser.setToolTipText("Import");
1852 * int value = chooser.showOpenDialog(this);
1854 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1855 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1857 v_client = new VamsasApplication(this);
1858 setupVamsasConnectedGui();
1859 v_client.initial_update(); // TODO: thread ?
1863 // store current data in session.
1864 v_client.push_update(); // TODO: thread
1868 protected void setupVamsasConnectedGui()
1870 vamsasStart.setText("Session Update");
1871 vamsasSave.setVisible(true);
1872 vamsasStop.setVisible(true);
1873 vamsasImport.setVisible(false); // Document import to existing session is
1874 // not possible for vamsas-client-1.0.
1877 protected void setupVamsasDisconnectedGui()
1879 vamsasSave.setVisible(false);
1880 vamsasStop.setVisible(false);
1881 vamsasImport.setVisible(true);
1882 vamsasStart.setText("New Vamsas Session");
1885 public void vamsasStop_actionPerformed(ActionEvent e)
1887 if (v_client != null)
1889 v_client.end_session();
1891 setupVamsasDisconnectedGui();
1895 protected void buildVamsasStMenu()
1897 if (v_client == null)
1899 String[] sess = null;
1902 sess = VamsasApplication.getSessionList();
1903 } catch (Exception e)
1905 jalview.bin.Cache.log.warn(
1906 "Problem getting current sessions list.", e);
1911 jalview.bin.Cache.log.debug("Got current sessions list: "
1912 + sess.length + " entries.");
1913 VamsasStMenu.removeAll();
1914 for (int i = 0; i < sess.length; i++)
1916 JMenuItem sessit = new JMenuItem();
1917 sessit.setText(sess[i]);
1918 sessit.setToolTipText("Connect to session " + sess[i]);
1919 final Desktop dsktp = this;
1920 final String mysesid = sess[i];
1921 sessit.addActionListener(new ActionListener()
1924 public void actionPerformed(ActionEvent e)
1926 if (dsktp.v_client == null)
1928 Thread rthr = new Thread(new Runnable()
1933 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1934 dsktp.setupVamsasConnectedGui();
1935 dsktp.v_client.initial_update();
1943 VamsasStMenu.add(sessit);
1945 // don't show an empty menu.
1946 VamsasStMenu.setVisible(sess.length > 0);
1951 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1952 VamsasStMenu.removeAll();
1953 VamsasStMenu.setVisible(false);
1958 // Not interested in the content. Just hide ourselves.
1959 VamsasStMenu.setVisible(false);
1963 public void vamsasSave_actionPerformed(ActionEvent e)
1965 if (v_client != null)
1967 JalviewFileChooser chooser = new JalviewFileChooser(
1968 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1969 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1971 { "Vamsas Document" }, "Vamsas Document");
1973 chooser.setFileView(new JalviewFileView());
1974 chooser.setDialogTitle("Save Vamsas Document Archive");
1976 int value = chooser.showSaveDialog(this);
1978 if (value == JalviewFileChooser.APPROVE_OPTION)
1980 java.io.File choice = chooser.getSelectedFile();
1981 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1982 + choice.getName());
1983 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1984 String warnmsg = null;
1985 String warnttl = null;
1988 v_client.vclient.storeDocument(choice);
1991 warnttl = "Serious Problem saving Vamsas Document";
1992 warnmsg = ex.toString();
1993 jalview.bin.Cache.log.error("Error Whilst saving document to "
1996 } catch (Exception ex)
1998 warnttl = "Problem saving Vamsas Document.";
1999 warnmsg = ex.toString();
2000 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2004 removeProgressPanel(progpanel);
2005 if (warnmsg != null)
2007 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2009 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2015 JPanel vamUpdate = null;
2018 * hide vamsas user gui bits when a vamsas document event is being handled.
2021 * true to hide gui, false to reveal gui
2023 public void setVamsasUpdate(boolean b)
2025 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2026 + (b ? "in progress" : "finished"));
2028 if (vamUpdate != null)
2030 this.removeProgressPanel(vamUpdate);
2034 vamUpdate = this.addProgressPanel("Updating vamsas session");
2036 vamsasStart.setVisible(!b);
2037 vamsasStop.setVisible(!b);
2038 vamsasSave.setVisible(!b);
2041 public JInternalFrame[] getAllFrames()
2043 return desktop.getAllFrames();
2047 * Checks the given url to see if it gives a response indicating that the user
2048 * should be informed of a new questionnaire.
2052 public void checkForQuestionnaire(String url)
2054 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2055 // javax.swing.SwingUtilities.invokeLater(jvq);
2056 new Thread(jvq).start();
2060 * Proxy class for JDesktopPane which optionally displays the current memory
2061 * usage and highlights the desktop area with a red bar if free memory runs
2066 public class MyDesktopPane extends JDesktopPane implements Runnable
2069 boolean showMemoryUsage = false;
2073 java.text.NumberFormat df;
2075 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2078 public MyDesktopPane(boolean showMemoryUsage)
2080 showMemoryUsage(showMemoryUsage);
2083 public void showMemoryUsage(boolean showMemoryUsage)
2085 this.showMemoryUsage = showMemoryUsage;
2086 if (showMemoryUsage)
2088 Thread worker = new Thread(this);
2093 public boolean isShowMemoryUsage()
2095 return showMemoryUsage;
2100 df = java.text.NumberFormat.getNumberInstance();
2101 df.setMaximumFractionDigits(2);
2102 runtime = Runtime.getRuntime();
2104 while (showMemoryUsage)
2108 maxMemory = runtime.maxMemory() / 1048576f;
2109 allocatedMemory = runtime.totalMemory() / 1048576f;
2110 freeMemory = runtime.freeMemory() / 1048576f;
2111 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2113 percentUsage = (totalFreeMemory / maxMemory) * 100;
2115 // if (percentUsage < 20)
2117 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2119 // instance.set.setBorder(border1);
2122 // sleep after showing usage
2124 } catch (Exception ex)
2126 ex.printStackTrace();
2131 public void paintComponent(Graphics g)
2133 if (showMemoryUsage && g != null && df != null)
2135 if (percentUsage < 20)
2136 g.setColor(Color.red);
2137 FontMetrics fm = g.getFontMetrics();
2141 "Total Free Memory: " + df.format(totalFreeMemory)
2142 + "MB; Max Memory: " + df.format(maxMemory)
2143 + "MB; " + df.format(percentUsage) + "%", 10,
2144 getHeight() - fm.getHeight());
2151 * fixes stacking order after a modal dialog to ensure windows that should be
2152 * on top actually are
2154 public void relayerWindows()
2159 protected JMenuItem groovyShell;
2161 public void doGroovyCheck()
2163 if (jalview.bin.Cache.groovyJarsPresent())
2165 groovyShell = new JMenuItem();
2166 groovyShell.setText("Groovy Console...");
2167 groovyShell.addActionListener(new ActionListener()
2169 public void actionPerformed(ActionEvent e)
2171 groovyShell_actionPerformed(e);
2174 toolsMenu.add(groovyShell);
2175 groovyShell.setVisible(true);
2180 * Accessor method to quickly get all the AlignmentFrames loaded.
2182 public static AlignFrame[] getAlignframes()
2184 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2190 Vector avp = new Vector();
2194 for (int i = frames.length - 1; i > -1; i--)
2196 if (frames[i] instanceof AlignFrame)
2198 AlignFrame af = (AlignFrame) frames[i];
2202 } catch (Exception ex)
2204 ex.printStackTrace();
2206 if (avp.size() == 0)
2210 AlignFrame afs[] = new AlignFrame[avp.size()];
2211 for (int i = 0, j = avp.size(); i < j; i++)
2213 afs[i] = (AlignFrame) avp.elementAt(i);
2219 public AppJmol[] getJmols()
2221 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2227 Vector avp = new Vector();
2231 for (int i = frames.length - 1; i > -1; i--)
2233 if (frames[i] instanceof AppJmol)
2235 AppJmol af = (AppJmol) frames[i];
2239 } catch (Exception ex)
2241 ex.printStackTrace();
2243 if (avp.size() == 0)
2247 AppJmol afs[] = new AppJmol[avp.size()];
2248 for (int i = 0, j = avp.size(); i < j; i++)
2250 afs[i] = (AppJmol) avp.elementAt(i);
2257 * Add Groovy Support to Jalview
2259 public void groovyShell_actionPerformed(ActionEvent e)
2261 // use reflection to avoid creating compilation dependency.
2262 if (!jalview.bin.Cache.groovyJarsPresent())
2265 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2269 Class gcClass = Desktop.class.getClassLoader().loadClass(
2270 "groovy.ui.Console");
2271 Constructor gccons = gcClass.getConstructor(null);
2272 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2274 { String.class, Object.class });
2275 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2276 Object gc = gccons.newInstance(null);
2277 setvar.invoke(gc, new Object[]
2278 { "Jalview", this });
2279 run.invoke(gc, null);
2280 } catch (Exception ex)
2282 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2284 .showInternalMessageDialog(
2287 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2288 "Jalview Groovy Support Failed",
2289 JOptionPane.ERROR_MESSAGE);
2294 * Progress bars managed by the IProgressIndicator method.
2296 private Hashtable<Long, JPanel> progressBars;
2298 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2303 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2305 public void setProgressBar(String message, long id)
2307 if (progressBars == null)
2309 progressBars = new Hashtable<Long, JPanel>();
2310 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2313 if (progressBars.get(new Long(id)) != null)
2315 JPanel progressPanel = progressBars.remove(new Long(id));
2316 if (progressBarHandlers.contains(new Long(id)))
2318 progressBarHandlers.remove(new Long(id));
2320 removeProgressPanel(progressPanel);
2324 progressBars.put(new Long(id), addProgressPanel(message));
2331 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2332 * jalview.gui.IProgressIndicatorHandler)
2334 public void registerHandler(final long id,
2335 final IProgressIndicatorHandler handler)
2337 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2340 "call setProgressBar before registering the progress bar's handler.");
2342 progressBarHandlers.put(new Long(id), handler);
2343 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2344 if (handler.canCancel())
2346 JButton cancel = new JButton("Cancel");
2347 final IProgressIndicator us = this;
2348 cancel.addActionListener(new ActionListener()
2351 public void actionPerformed(ActionEvent e)
2353 handler.cancelActivity(id);
2356 + ((JLabel) progressPanel.getComponent(0))
2360 progressPanel.add(cancel, BorderLayout.EAST);
2366 * @return true if any progress bars are still active
2369 public boolean operationInProgress()
2371 if (progressBars != null && progressBars.size() > 0)
2379 * This will return the first AlignFrame viewing AlignViewport av. It will
2380 * break if there are more than one AlignFrames viewing a particular av. This
2383 * @return alignFrame for av
2385 public static AlignFrame getAlignFrameFor(AlignViewport av)
2387 if (desktop != null)
2389 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2390 for (int panel = 0; aps != null && panel < aps.length; panel++)
2392 if (aps[panel] != null && aps[panel].av == av)
2394 return aps[panel].alignFrame;
2401 public VamsasApplication getVamsasApplication()
2408 * flag set if jalview GUI is being operated programmatically
2410 private boolean inBatchMode = false;
2413 * check if jalview GUI is being operated programmatically
2415 * @return inBatchMode
2417 public boolean isInBatchMode()
2423 * set flag if jalview GUI is being operated programmatically
2425 * @param inBatchMode
2427 public void setInBatchMode(boolean inBatchMode)
2429 this.inBatchMode = inBatchMode;
2432 public void startServiceDiscovery()
2434 startServiceDiscovery(false);
2437 public void startServiceDiscovery(boolean blocking)
2439 boolean alive = true;
2440 Thread t0 = null, t1 = null, t2 = null;
2442 // todo: changesupport handlers need to be transferred
2443 if (discoverer == null)
2445 discoverer = new jalview.ws.jws1.Discoverer();
2446 // register PCS handler for desktop.
2447 discoverer.addPropertyChangeListener(changeSupport);
2449 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2450 // until we phase out completely
2453 (t0 = new Thread(discoverer)).start();
2458 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2460 // EnfinEnvision web service menu entries are rebuild every time the
2461 // menu is shown, so no changeSupport events are needed.
2462 jalview.ws.EnfinEnvision2OneWay.getInstance();
2463 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2466 } catch (Exception e)
2469 .info("Exception when trying to launch Envision2 workflow discovery.",
2471 Cache.log.info(e.getStackTrace());
2473 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2475 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2477 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2479 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2485 // TODO: do rest service discovery
2494 } catch (Exception e)
2497 alive = (t1 != null && t1.isAlive())
2498 || (t2 != null && t2.isAlive())
2499 || (t3 != null && t3.isAlive())
2500 || (t0 != null && t0.isAlive());
2506 * called to check if the service discovery process completed successfully.
2510 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2512 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2514 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2515 .getErrorMessages();
2518 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2520 if (serviceChangedDialog == null)
2522 // only run if we aren't already displaying one of these.
2523 addDialogThread(serviceChangedDialog = new Runnable()
2529 * JalviewDialog jd =new JalviewDialog() {
2531 * @Override protected void cancelPressed() { // TODO
2532 * Auto-generated method stub
2534 * }@Override protected void okPressed() { // TODO
2535 * Auto-generated method stub
2537 * }@Override protected void raiseClosed() { // TODO
2538 * Auto-generated method stub
2540 * } }; jd.initDialogFrame(new
2541 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2542 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2543 * + " or mis-configured HTTP proxy settings.<br/>" +
2544 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2546 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2547 * ), true, true, "Web Service Configuration Problem", 450,
2550 * jd.waitForInput();
2556 "<html><table width=\"450\"><tr><td>"
2558 + "</td></tr></table>"
2559 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2560 + " or mis-configured HTTP proxy settings.</p>"
2561 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2562 + " Tools->Preferences dialog box to change them.</p></html>"),
2563 "Web Service Configuration Problem",
2564 JOptionPane.DEFAULT_OPTION,
2565 JOptionPane.ERROR_MESSAGE);
2566 serviceChangedDialog = null;
2575 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2582 private Runnable serviceChangedDialog = null;
2585 * start a thread to open a URL in the configured browser. Pops up a warning
2586 * dialog to the user if there is an exception when calling out to the browser
2591 public static void showUrl(final String url)
2593 showUrl(url, Desktop.instance);
2597 * Like showUrl but allows progress handler to be specified
2601 * (null) or object implementing IProgressIndicator
2603 public static void showUrl(final String url,
2604 final IProgressIndicator progress)
2606 new Thread(new Runnable()
2612 if (progress != null)
2614 progress.setProgressBar("Opening " + url, this.hashCode());
2616 jalview.util.BrowserLauncher.openURL(url);
2617 } catch (Exception ex)
2620 .showInternalMessageDialog(
2622 "Unixers: Couldn't find default web browser."
2623 + "\nAdd the full path to your browser in Preferences.",
2624 "Web browser not found",
2625 JOptionPane.WARNING_MESSAGE);
2627 ex.printStackTrace();
2629 if (progress != null)
2631 progress.setProgressBar(null, this.hashCode());
2637 public static WsParamSetManager wsparamManager = null;
2639 public static ParamManager getUserParameterStore()
2641 if (wsparamManager == null)
2643 wsparamManager = new WsParamSetManager();
2645 return wsparamManager;
2649 * static hyperlink handler proxy method for use by Jalview's internal windows
2653 public static void hyperlinkUpdate(HyperlinkEvent e)
2655 if (e.getEventType() == EventType.ACTIVATED)
2660 url = e.getURL().toString();
2661 Desktop.showUrl(url);
2662 } catch (Exception x)
2666 if (Cache.log != null)
2668 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2672 System.err.println("Couldn't handle string " + url
2676 // ignore any exceptions due to dud links.
2683 * single thread that handles display of dialogs to user.
2685 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2688 * flag indicating if dialogExecutor should try to acquire a permit
2690 private volatile boolean dialogPause = true;
2695 private java.util.concurrent.Semaphore block = new Semaphore(0);
2698 * add another dialog thread to the queue
2702 public void addDialogThread(final Runnable prompter)
2704 dialogExecutor.submit(new Runnable()
2713 } catch (InterruptedException x)
2718 if (instance == null)
2724 SwingUtilities.invokeAndWait(prompter);
2725 } catch (Exception q)
2727 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2733 public void startDialogQueue()
2735 // set the flag so we don't pause waiting for another permit and semaphore
2736 // the current task to begin
2737 dialogPause = false;