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.util.MessageManager;
27 import jalview.ws.params.ParamManager;
29 import java.awt.BorderLayout;
30 import java.awt.Color;
31 import java.awt.Dimension;
32 import java.awt.FontMetrics;
33 import java.awt.Graphics;
34 import java.awt.GridLayout;
35 import java.awt.Point;
36 import java.awt.Rectangle;
37 import java.awt.Toolkit;
38 import java.awt.datatransfer.Clipboard;
39 import java.awt.datatransfer.ClipboardOwner;
40 import java.awt.datatransfer.DataFlavor;
41 import java.awt.datatransfer.Transferable;
42 import java.awt.dnd.DnDConstants;
43 import java.awt.dnd.DropTargetDragEvent;
44 import java.awt.dnd.DropTargetDropEvent;
45 import java.awt.dnd.DropTargetEvent;
46 import java.awt.dnd.DropTargetListener;
47 import java.awt.event.ActionEvent;
48 import java.awt.event.ActionListener;
49 import java.awt.event.FocusEvent;
50 import java.awt.event.FocusListener;
51 import java.awt.event.MouseAdapter;
52 import java.awt.event.MouseEvent;
53 import java.awt.event.MouseListener;
54 import java.awt.event.WindowAdapter;
55 import java.awt.event.WindowEvent;
56 import java.beans.PropertyChangeEvent;
57 import java.beans.PropertyChangeListener;
58 import java.beans.PropertyVetoException;
59 import java.io.BufferedInputStream;
61 import java.io.FileOutputStream;
62 import java.lang.reflect.Constructor;
64 import java.util.ArrayList;
65 import java.util.Hashtable;
66 import java.util.StringTokenizer;
67 import java.util.Vector;
68 import java.util.concurrent.ExecutorService;
69 import java.util.concurrent.Executors;
70 import java.util.concurrent.Semaphore;
72 import javax.swing.DefaultDesktopManager;
73 import javax.swing.DesktopManager;
74 import javax.swing.JButton;
75 import javax.swing.JComboBox;
76 import javax.swing.JComponent;
77 import javax.swing.JDesktopPane;
78 import javax.swing.JFrame;
79 import javax.swing.JInternalFrame;
80 import javax.swing.JLabel;
81 import javax.swing.JMenuItem;
82 import javax.swing.JOptionPane;
83 import javax.swing.JPanel;
84 import javax.swing.JPopupMenu;
85 import javax.swing.JProgressBar;
86 import javax.swing.SwingUtilities;
87 import javax.swing.event.HyperlinkEvent;
88 import javax.swing.event.MenuEvent;
89 import javax.swing.event.MenuListener;
90 import javax.swing.event.HyperlinkEvent.EventType;
97 * @version $Revision: 1.155 $
99 public class Desktop extends jalview.jbgui.GDesktop implements
100 DropTargetListener, ClipboardOwner, IProgressIndicator,
101 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);
303 // This line prevents Windows Look&Feel resizing all new windows to maximum
304 // if previous window was maximised
305 desktop.setDesktopManager(new MyDesktopManager(
306 new DefaultDesktopManager()));
308 Rectangle dims = getLastKnownDimensions("");
315 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
316 setBounds((int) (screenSize.width - 900) / 2,
317 (int) (screenSize.height - 650) / 2, 900, 650);
319 jconsole = new Console(this, showjconsole);
320 // add essential build information
321 jconsole.setHeader("Jalview Desktop "
322 + jalview.bin.Cache.getProperty("VERSION") + "\n"
324 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
325 + "Java version: " + System.getProperty("java.version") + "\n"
326 + System.getProperty("os.arch") + " "
327 + System.getProperty("os.name") + " "
328 + System.getProperty("os.version"));
330 showConsole(showjconsole);
332 showNews.setVisible(false);
334 this.addWindowListener(new WindowAdapter()
336 public void windowClosing(WindowEvent evt)
343 this.addMouseListener(ma = new MouseAdapter()
345 public void mousePressed(MouseEvent evt)
347 if (SwingUtilities.isRightMouseButton(evt))
349 showPasteMenu(evt.getX(), evt.getY());
353 desktop.addMouseListener(ma);
355 this.addFocusListener(new FocusListener()
359 public void focusLost(FocusEvent e)
361 // TODO Auto-generated method stub
366 public void focusGained(FocusEvent e)
368 Cache.log.debug("Relaying windows after focus gain");
369 // make sure that we sort windows properly after we gain focus
370 instance.relayerWindows();
373 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
374 // Spawn a thread that shows the splashscreen
375 SwingUtilities.invokeLater(new Runnable()
384 // Thread off a new instance of the file chooser - this reduces the time it
385 // takes to open it later on.
386 new Thread(new Runnable()
390 Cache.log.debug("Filechooser init thread started.");
391 JalviewFileChooser chooser = new JalviewFileChooser(
392 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
393 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
394 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
395 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
396 Cache.log.debug("Filechooser init thread finished.");
399 // Add the service change listener
400 changeSupport.addJalviewPropertyChangeListener("services",
401 new PropertyChangeListener()
405 public void propertyChange(PropertyChangeEvent evt)
407 Cache.log.debug("Firing service changed event for "
408 + evt.getNewValue());
409 JalviewServicesChanged(evt);
415 public void checkForNews()
417 final Desktop me = this;
418 // Thread off the news reader, in case there are connection problems.
419 addDialogThread(new Runnable()
424 Cache.log.debug("Starting news thread.");
426 jvnews = new BlogReader(me);
427 showNews.setVisible(true);
428 Cache.log.debug("Completed news thread.");
433 protected void showNews_actionPerformed(ActionEvent e)
435 showNews(showNews.isSelected());
438 void showNews(boolean visible)
441 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
442 showNews.setSelected(visible);
443 if (visible && !jvnews.isVisible())
445 new Thread(new Runnable()
450 long instance = System.currentTimeMillis();
451 Desktop.instance.setProgressBar("Refreshing news", instance);
452 jvnews.refreshNews();
453 Desktop.instance.setProgressBar(null, instance);
462 * recover the last known dimensions for a jalview window
465 * - empty string is desktop, all other windows have unique prefix
466 * @return null or last known dimensions scaled to current geometry (if last
467 * window geom was known)
469 Rectangle getLastKnownDimensions(String windowName)
471 // TODO: lock aspect ratio for scaling desktop Bug #0058199
472 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
473 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
474 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
475 String width = jalview.bin.Cache.getProperty(windowName
477 String height = jalview.bin.Cache.getProperty(windowName
479 if ((x != null) && (y != null) && (width != null) && (height != null))
481 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
482 .parseInt(width), ih = Integer.parseInt(height);
483 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
485 // attempt #1 - try to cope with change in screen geometry - this
486 // version doesn't preserve original jv aspect ratio.
487 // take ratio of current screen size vs original screen size.
488 double sw = ((1f * screenSize.width) / (1f * Integer
489 .parseInt(jalview.bin.Cache
490 .getProperty("SCREENGEOMETRY_WIDTH"))));
491 double sh = ((1f * screenSize.height) / (1f * Integer
492 .parseInt(jalview.bin.Cache
493 .getProperty("SCREENGEOMETRY_HEIGHT"))));
494 // rescale the bounds depending upon the current screen geometry.
495 ix = (int) (ix * sw);
496 iw = (int) (iw * sw);
497 iy = (int) (iy * sh);
498 ih = (int) (ih * sh);
499 while (ix >= screenSize.width)
501 jalview.bin.Cache.log
502 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
503 ix -= screenSize.width;
505 while (iy >= screenSize.height)
507 jalview.bin.Cache.log
508 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
509 iy -= screenSize.height;
511 jalview.bin.Cache.log.debug("Got last known dimensions for "
512 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
515 // return dimensions for new instance
516 return new Rectangle(ix, iy, iw, ih);
521 private void doVamsasClientCheck()
523 if (jalview.bin.Cache.vamsasJarsPresent())
525 setupVamsasDisconnectedGui();
526 VamsasMenu.setVisible(true);
527 final Desktop us = this;
528 VamsasMenu.addMenuListener(new MenuListener()
530 // this listener remembers when the menu was first selected, and
531 // doesn't rebuild the session list until it has been cleared and
533 boolean refresh = true;
535 public void menuCanceled(MenuEvent e)
540 public void menuDeselected(MenuEvent e)
545 public void menuSelected(MenuEvent e)
549 us.buildVamsasStMenu();
554 vamsasStart.setVisible(true);
558 void showPasteMenu(int x, int y)
560 JPopupMenu popup = new JPopupMenu();
561 JMenuItem item = new JMenuItem("Paste To New Window");
562 item.addActionListener(new ActionListener()
564 public void actionPerformed(ActionEvent evt)
571 popup.show(this, x, y);
578 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
579 Transferable contents = c.getContents(this);
581 if (contents != null)
583 String file = (String) contents
584 .getTransferData(DataFlavor.stringFlavor);
586 String format = new IdentifyFile().Identify(file,
587 FormatAdapter.PASTE);
589 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
592 } catch (Exception ex)
595 .println("Unable to paste alignment from system clipboard:\n"
601 * Adds and opens the given frame to the desktop
612 public static synchronized void addInternalFrame(
613 final JInternalFrame frame, String title, int w, int h)
615 addInternalFrame(frame, title, w, h, true);
632 public static synchronized void addInternalFrame(
633 final JInternalFrame frame, String title, int w, int h,
637 // TODO: allow callers to determine X and Y position of frame (eg. via
639 // TODO: consider fixing method to update entries in the window submenu with
640 // the current window title
642 frame.setTitle(title);
643 if (frame.getWidth() < 1 || frame.getHeight() < 1)
647 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
648 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
649 // IF JALVIEW IS RUNNING HEADLESS
650 // ///////////////////////////////////////////////
651 if (instance == null || (System.getProperty("java.awt.headless") != null
652 && System.getProperty("java.awt.headless").equals("true")))
659 frame.setVisible(true);
660 frame.setClosable(true);
661 frame.setResizable(resizable);
662 frame.setMaximizable(resizable);
663 frame.setIconifiable(resizable);
664 frame.setFrameIcon(null);
666 if (frame.getX() < 1 && frame.getY() < 1)
668 frame.setLocation(xOffset * openFrameCount, yOffset
669 * ((openFrameCount - 1) % 10) + yOffset);
672 final JMenuItem menuItem = new JMenuItem(title);
673 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
675 public void internalFrameActivated(
676 javax.swing.event.InternalFrameEvent evt)
678 JInternalFrame itf = desktop.getSelectedFrame();
686 public void internalFrameClosed(
687 javax.swing.event.InternalFrameEvent evt)
689 PaintRefresher.RemoveComponent(frame);
691 windowMenu.remove(menuItem);
692 JInternalFrame itf = desktop.getSelectedFrame();
701 menuItem.addActionListener(new ActionListener()
703 public void actionPerformed(ActionEvent e)
707 frame.setSelected(true);
708 frame.setIcon(false);
709 } catch (java.beans.PropertyVetoException ex)
715 menuItem.addMouseListener(new MouseListener()
719 public void mouseReleased(MouseEvent e)
724 public void mousePressed(MouseEvent e)
729 public void mouseExited(MouseEvent e)
733 frame.setSelected(false);
734 } catch (PropertyVetoException e1)
740 public void mouseEntered(MouseEvent e)
744 frame.setSelected(true);
745 } catch (PropertyVetoException e1)
751 public void mouseClicked(MouseEvent e)
757 windowMenu.add(menuItem);
763 frame.setSelected(true);
764 frame.requestFocus();
765 } catch (java.beans.PropertyVetoException ve)
767 } catch (java.lang.ClassCastException cex)
770 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
775 public void lostOwnership(Clipboard clipboard, Transferable contents)
779 Desktop.jalviewClipboard = null;
782 internalCopy = false;
785 public void dragEnter(DropTargetDragEvent evt)
789 public void dragExit(DropTargetEvent evt)
793 public void dragOver(DropTargetDragEvent evt)
797 public void dropActionChanged(DropTargetDragEvent evt)
807 public void drop(DropTargetDropEvent evt)
809 Transferable t = evt.getTransferable();
810 java.util.List files = null;
811 java.util.List protocols = null;
815 DataFlavor uriListFlavor = new DataFlavor(
816 "text/uri-list;class=java.lang.String");
817 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
819 // Works on Windows and MacOSX
820 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
821 files = (java.util.List) t
822 .getTransferData(DataFlavor.javaFileListFlavor);
824 else if (t.isDataFlavorSupported(uriListFlavor))
826 // This is used by Unix drag system
827 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
828 String data = (String) t.getTransferData(uriListFlavor);
829 files = new java.util.ArrayList(1);
830 protocols = new java.util.ArrayList(1);
831 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
832 data, "\r\n"); st.hasMoreTokens();)
834 String s = st.nextToken();
835 if (s.startsWith("#"))
837 // the line is a comment (as per the RFC 2483)
840 java.net.URI uri = new java.net.URI(s);
841 if (uri.getScheme().toLowerCase().startsWith("http"))
843 protocols.add(FormatAdapter.URL);
844 files.add(uri.toString());
848 // otherwise preserve old behaviour: catch all for file objects
849 java.io.File file = new java.io.File(uri);
850 protocols.add(FormatAdapter.FILE);
851 files.add(file.toString());
855 } catch (Exception e)
863 for (int i = 0; i < files.size(); i++)
865 String file = files.get(i).toString();
866 String protocol = (protocols == null) ? FormatAdapter.FILE
867 : (String) protocols.get(i);
868 String format = null;
870 if (file.endsWith(".jar"))
877 format = new IdentifyFile().Identify(file, protocol);
880 new FileLoader().LoadFile(file, protocol, format);
883 } catch (Exception ex)
895 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
897 JalviewFileChooser chooser = new JalviewFileChooser(
898 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
899 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
900 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
901 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
903 chooser.setFileView(new JalviewFileView());
904 chooser.setDialogTitle("Open local file");
905 chooser.setToolTipText("Open");
907 int value = chooser.showOpenDialog(this);
909 if (value == JalviewFileChooser.APPROVE_OPTION)
911 String choice = chooser.getSelectedFile().getPath();
912 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
913 .getSelectedFile().getParent());
915 String format = null;
916 if (chooser.getSelectedFormat()!=null && chooser.getSelectedFormat().equals("Jalview"))
922 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
925 if (viewport != null)
927 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
932 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
943 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
945 // This construct allows us to have a wider textfield
947 JLabel label = new JLabel(MessageManager.getString("label.input_file_url"));
948 final JComboBox history = new JComboBox();
950 JPanel panel = new JPanel(new GridLayout(2, 1));
953 history.setPreferredSize(new Dimension(400, 20));
954 history.setEditable(true);
955 history.addItem("http://www.");
957 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
961 if (historyItems != null)
963 st = new StringTokenizer(historyItems, "\t");
965 while (st.hasMoreTokens())
967 history.addItem(st.nextElement());
971 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
972 MessageManager.getString("label.input_alignment_from_url"), JOptionPane.OK_CANCEL_OPTION);
974 if (reply != JOptionPane.OK_OPTION)
979 String url = history.getSelectedItem().toString();
981 if (url.toLowerCase().endsWith(".jar"))
983 if (viewport != null)
985 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
990 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
995 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
997 if (format.equals("URL NOT FOUND"))
999 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1000 "Couldn't locate " + url, "URL not found",
1001 JOptionPane.WARNING_MESSAGE);
1006 if (viewport != null)
1008 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1012 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1023 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1025 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1026 cap.setForInput(viewport);
1027 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1035 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1037 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1038 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1040 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1041 getBounds().y, getWidth(), getHeight()));
1043 if (jconsole != null)
1045 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1046 jconsole.stopConsole();
1050 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1053 if (dialogExecutor != null)
1055 dialogExecutor.shutdownNow();
1061 private void storeLastKnownDimensions(String string, Rectangle jc)
1063 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1064 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1065 + " height:" + jc.height);
1067 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1068 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1069 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1070 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1079 public void aboutMenuItem_actionPerformed(ActionEvent e)
1081 // StringBuffer message = getAboutMessage(false);
1082 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1084 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1085 new Thread(new Runnable()
1089 new SplashScreen(true);
1094 public StringBuffer getAboutMessage(boolean shortv)
1096 StringBuffer message = new StringBuffer();
1097 message.append("<html>");
1100 message.append("<h1><strong>Version: "
1101 + jalview.bin.Cache.getProperty("VERSION")
1102 + "</strong></h1><br>");
1103 message.append("<strong>Last Updated: <em>"
1104 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1105 + "</em></strong>");
1111 message.append("<strong>Version "
1112 + jalview.bin.Cache.getProperty("VERSION")
1113 + "; last updated: "
1114 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1117 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1120 message.append("<br>...Checking latest version...</br>");
1122 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1123 .equals(jalview.bin.Cache.getProperty("VERSION")))
1125 boolean red = false;
1126 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1127 .indexOf("automated build") == -1)
1130 // Displayed when code version and jnlp version do not match and code
1131 // version is not a development build
1132 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1135 message.append("<br>!! Version "
1136 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1138 + " is available for download from "
1139 + jalview.bin.Cache.getDefault("www.jalview.org",
1140 "http://www.jalview.org") + " !!");
1143 message.append("</div>");
1146 message.append("<br>Authors: "
1150 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1151 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1152 + "<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"
1153 + "<br>If you use Jalview, please cite:"
1154 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1155 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1156 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1167 public void documentationMenuItem_actionPerformed(ActionEvent e)
1171 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1172 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1173 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1175 javax.help.HelpBroker hb = hs.createHelpBroker();
1176 hb.setCurrentID("home");
1177 hb.setDisplayed(true);
1178 } catch (Exception ex)
1183 public void closeAll_actionPerformed(ActionEvent e)
1185 JInternalFrame[] frames = desktop.getAllFrames();
1186 for (int i = 0; i < frames.length; i++)
1190 frames[i].setClosed(true);
1191 } catch (java.beans.PropertyVetoException ex)
1195 System.out.println("ALL CLOSED");
1196 if (v_client != null)
1198 // TODO clear binding to vamsas document objects on close_all
1203 public void raiseRelated_actionPerformed(ActionEvent e)
1205 reorderAssociatedWindows(false, false);
1208 public void minimizeAssociated_actionPerformed(ActionEvent e)
1210 reorderAssociatedWindows(true, false);
1213 void closeAssociatedWindows()
1215 reorderAssociatedWindows(false, true);
1221 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1224 protected void garbageCollect_actionPerformed(ActionEvent e)
1226 // We simply collect the garbage
1227 jalview.bin.Cache.log.debug("Collecting garbage...");
1229 jalview.bin.Cache.log.debug("Finished garbage collection.");
1236 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1239 protected void showMemusage_actionPerformed(ActionEvent e)
1241 desktop.showMemoryUsage(showMemusage.isSelected());
1248 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1251 protected void showConsole_actionPerformed(ActionEvent e)
1253 showConsole(showConsole.isSelected());
1256 Console jconsole = null;
1259 * control whether the java console is visible or not
1263 void showConsole(boolean selected)
1265 showConsole.setSelected(selected);
1266 // TODO: decide if we should update properties file
1267 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1269 jconsole.setVisible(selected);
1272 void reorderAssociatedWindows(boolean minimize, boolean close)
1274 JInternalFrame[] frames = desktop.getAllFrames();
1275 if (frames == null || frames.length < 1)
1280 AlignViewport source = null, target = null;
1281 if (frames[0] instanceof AlignFrame)
1283 source = ((AlignFrame) frames[0]).getCurrentView();
1285 else if (frames[0] instanceof TreePanel)
1287 source = ((TreePanel) frames[0]).getViewPort();
1289 else if (frames[0] instanceof PCAPanel)
1291 source = ((PCAPanel) frames[0]).av;
1293 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1295 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1300 for (int i = 0; i < frames.length; i++)
1303 if (frames[i] == null)
1307 if (frames[i] instanceof AlignFrame)
1309 target = ((AlignFrame) frames[i]).getCurrentView();
1311 else if (frames[i] instanceof TreePanel)
1313 target = ((TreePanel) frames[i]).getViewPort();
1315 else if (frames[i] instanceof PCAPanel)
1317 target = ((PCAPanel) frames[i]).av;
1319 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1321 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1324 if (source == target)
1330 frames[i].setClosed(true);
1334 frames[i].setIcon(minimize);
1337 frames[i].toFront();
1341 } catch (java.beans.PropertyVetoException ex)
1355 protected void preferences_actionPerformed(ActionEvent e)
1366 public void saveState_actionPerformed(ActionEvent e)
1368 JalviewFileChooser chooser = new JalviewFileChooser(
1369 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1370 { "jar" }, new String[]
1371 { "Jalview Project" }, "Jalview Project");
1373 chooser.setFileView(new JalviewFileView());
1374 chooser.setDialogTitle("Save State");
1376 int value = chooser.showSaveDialog(this);
1378 if (value == JalviewFileChooser.APPROVE_OPTION)
1380 final Desktop me = this;
1381 final java.io.File choice = chooser.getSelectedFile();
1382 new Thread(new Runnable()
1387 setProgressBar("Saving jalview project " + choice.getName(),
1389 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1390 choice.getParent());
1391 // TODO catch and handle errors for savestate
1392 // TODO prevent user from messing with the Desktop whilst we're saving
1395 new Jalview2XML().SaveState(choice);
1396 } catch (OutOfMemoryError oom)
1398 new OOMWarning("Whilst saving current state to "
1399 + choice.getName(), oom);
1400 } catch (Exception ex)
1403 "Problems whilst trying to save to " + choice.getName(),
1405 JOptionPane.showMessageDialog(
1407 "Error whilst saving current state to "
1408 + choice.getName(), "Couldn't save project",
1409 JOptionPane.WARNING_MESSAGE);
1411 setProgressBar(null, choice.hashCode());
1423 public void loadState_actionPerformed(ActionEvent e)
1425 JalviewFileChooser chooser = new JalviewFileChooser(
1426 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1427 { "jar" }, new String[]
1428 { "Jalview Project" }, "Jalview Project");
1429 chooser.setFileView(new JalviewFileView());
1430 chooser.setDialogTitle("Restore state");
1432 int value = chooser.showOpenDialog(this);
1434 if (value == JalviewFileChooser.APPROVE_OPTION)
1436 final String choice = chooser.getSelectedFile().getAbsolutePath();
1437 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1438 .getSelectedFile().getParent());
1439 new Thread(new Runnable()
1443 setProgressBar("loading jalview project " + choice,
1447 new Jalview2XML().LoadJalviewAlign(choice);
1448 } catch (OutOfMemoryError oom)
1450 new OOMWarning("Whilst loading project from " + choice, oom);
1451 } catch (Exception ex)
1453 Cache.log.error("Problems whilst loading project from "
1455 JOptionPane.showMessageDialog(Desktop.desktop,
1456 "Error whilst loading project from " + choice,
1457 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1459 setProgressBar(null, choice.hashCode());
1465 public void inputSequence_actionPerformed(ActionEvent e)
1467 new SequenceFetcher(this);
1470 JPanel progressPanel;
1472 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1474 public void startLoading(final String fileName)
1476 if (fileLoadingCount == 0)
1478 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1484 private JPanel addProgressPanel(String string)
1486 if (progressPanel == null)
1488 progressPanel = new JPanel(new GridLayout(1, 1));
1489 totalProgressCount = 0;
1490 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1492 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1493 JProgressBar progressBar = new JProgressBar();
1494 progressBar.setIndeterminate(true);
1496 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1498 thisprogress.add(progressBar, BorderLayout.CENTER);
1499 progressPanel.add(thisprogress);
1500 ((GridLayout) progressPanel.getLayout())
1501 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1502 ++totalProgressCount;
1503 instance.validate();
1504 return thisprogress;
1507 int totalProgressCount = 0;
1509 private void removeProgressPanel(JPanel progbar)
1511 if (progressPanel != null)
1513 synchronized(progressPanel) {
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;
1527 public void stopLoading()
1530 if (fileLoadingCount < 1)
1532 while (fileLoadingPanels.size()>0)
1534 removeProgressPanel(fileLoadingPanels.remove(0));
1536 fileLoadingPanels.clear();
1537 fileLoadingCount = 0;
1542 public static int getViewCount(String alignmentId)
1544 AlignViewport[] aps = getViewports(alignmentId);
1545 return (aps == null) ? 0 : aps.length;
1550 * @param alignmentId
1551 * @return all AlignmentPanels concerning the alignmentId sequence set
1553 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1556 if (Desktop.desktop == null)
1558 // no frames created and in headless mode
1559 // TODO: verify that frames are recoverable when in headless mode
1562 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1563 ArrayList aps = new ArrayList();
1564 for (int t = 0; t < frames.length; t++)
1566 if (frames[t] instanceof AlignFrame)
1568 AlignFrame af = (AlignFrame) frames[t];
1569 for (int a = 0; a < af.alignPanels.size(); a++)
1571 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1572 .elementAt(a)).av.getSequenceSetId()))
1574 aps.add(af.alignPanels.elementAt(a));
1579 if (aps.size() == 0)
1583 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1584 for (int t = 0; t < vap.length; t++)
1586 vap[t] = (AlignmentPanel) aps.get(t);
1592 * get all the viewports on an alignment.
1594 * @param sequenceSetId
1595 * unique alignment id
1596 * @return all viewports on the alignment bound to sequenceSetId
1598 public static AlignViewport[] getViewports(String sequenceSetId)
1600 Vector viewp = new Vector();
1601 if (desktop != null)
1603 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1605 for (int t = 0; t < frames.length; t++)
1607 if (frames[t] instanceof AlignFrame)
1609 AlignFrame afr = ((AlignFrame) frames[t]);
1610 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1612 if (afr.alignPanels != null)
1614 for (int a = 0; a < afr.alignPanels.size(); a++)
1616 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1617 .elementAt(a)).av.getSequenceSetId()))
1619 viewp.addElement(((AlignmentPanel) afr.alignPanels
1626 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1631 if (viewp.size() > 0)
1633 AlignViewport[] vp = new AlignViewport[viewp.size()];
1641 public void explodeViews(AlignFrame af)
1643 int size = af.alignPanels.size();
1649 for (int i = 0; i < size; i++)
1651 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1652 AlignFrame newaf = new AlignFrame(ap);
1653 if (ap.av.explodedPosition != null
1654 && !ap.av.explodedPosition.equals(af.getBounds()))
1656 newaf.setBounds(ap.av.explodedPosition);
1659 ap.av.gatherViewsHere = false;
1661 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1662 AlignFrame.DEFAULT_HEIGHT);
1665 af.alignPanels.clear();
1666 af.closeMenuItem_actionPerformed(true);
1670 public void gatherViews(AlignFrame source)
1672 source.viewport.gatherViewsHere = true;
1673 source.viewport.explodedPosition = source.getBounds();
1674 JInternalFrame[] frames = desktop.getAllFrames();
1675 String viewId = source.viewport.getSequenceSetId();
1677 for (int t = 0; t < frames.length; t++)
1679 if (frames[t] instanceof AlignFrame && frames[t] != source)
1681 AlignFrame af = (AlignFrame) frames[t];
1682 boolean gatherThis = false;
1683 for (int a = 0; a < af.alignPanels.size(); a++)
1685 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1686 if (viewId.equals(ap.av.getSequenceSetId()))
1689 ap.av.gatherViewsHere = false;
1690 ap.av.explodedPosition = af.getBounds();
1691 source.addAlignmentPanel(ap, false);
1697 af.alignPanels.clear();
1698 af.closeMenuItem_actionPerformed(true);
1705 jalview.gui.VamsasApplication v_client = null;
1707 public void vamsasImport_actionPerformed(ActionEvent e)
1709 if (v_client == null)
1711 // Load and try to start a session.
1712 JalviewFileChooser chooser = new JalviewFileChooser(
1713 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1715 chooser.setFileView(new JalviewFileView());
1716 chooser.setDialogTitle("Open a saved VAMSAS session");
1717 chooser.setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1719 int value = chooser.showOpenDialog(this);
1721 if (value == JalviewFileChooser.APPROVE_OPTION)
1723 String fle = chooser.getSelectedFile().toString();
1724 if (!vamsasImport(chooser.getSelectedFile()))
1726 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1727 MessageManager.formatMessage("label.couldnt_import_as_vamsas_session", new String[]{fle}),
1728 MessageManager.getString("label.vamsas_document_import_failed"),
1729 JOptionPane.ERROR_MESSAGE);
1735 jalview.bin.Cache.log
1736 .error("Implementation error - load session from a running session is not supported.");
1741 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1744 * @return true if import was a success and a session was started.
1746 public boolean vamsasImport(URL url)
1748 // TODO: create progress bar
1749 if (v_client != null)
1752 jalview.bin.Cache.log
1753 .error("Implementation error - load session from a running session is not supported.");
1759 // copy the URL content to a temporary local file
1760 // TODO: be a bit cleverer here with nio (?!)
1761 File file = File.createTempFile("vdocfromurl", ".vdj");
1762 FileOutputStream fos = new FileOutputStream(file);
1763 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1764 byte[] buffer = new byte[2048];
1766 while ((ln = bis.read(buffer)) > -1)
1768 fos.write(buffer, 0, ln);
1772 v_client = new jalview.gui.VamsasApplication(this, file,
1773 url.toExternalForm());
1774 } catch (Exception ex)
1776 jalview.bin.Cache.log.error(
1777 "Failed to create new vamsas session from contents of URL "
1781 setupVamsasConnectedGui();
1782 v_client.initial_update(); // TODO: thread ?
1783 return v_client.inSession();
1787 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1790 * @return true if import was a success and a session was started.
1792 public boolean vamsasImport(File file)
1794 if (v_client != null)
1797 jalview.bin.Cache.log
1798 .error("Implementation error - load session from a running session is not supported.");
1802 setProgressBar("Importing VAMSAS session from " + file.getName(),
1806 v_client = new jalview.gui.VamsasApplication(this, file, null);
1807 } catch (Exception ex)
1809 setProgressBar("Importing VAMSAS session from " + file.getName(),
1811 jalview.bin.Cache.log.error(
1812 "New vamsas session from existing session file failed:", ex);
1815 setupVamsasConnectedGui();
1816 v_client.initial_update(); // TODO: thread ?
1817 setProgressBar("Importing VAMSAS session from " + file.getName(),
1819 return v_client.inSession();
1822 public boolean joinVamsasSession(String mysesid)
1824 if (v_client != null)
1827 "Trying to join a vamsas session when another is already connected.");
1829 if (mysesid == null)
1831 throw new Error("Invalid vamsas session id.");
1833 v_client = new VamsasApplication(this, mysesid);
1834 setupVamsasConnectedGui();
1835 v_client.initial_update();
1836 return (v_client.inSession());
1839 public void vamsasStart_actionPerformed(ActionEvent e)
1841 if (v_client == null)
1844 // we just start a default session for moment.
1846 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1847 * getProperty("LAST_DIRECTORY"));
1849 * chooser.setFileView(new JalviewFileView());
1850 * chooser.setDialogTitle("Load Vamsas file");
1851 * chooser.setToolTipText("Import");
1853 * int value = chooser.showOpenDialog(this);
1855 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1856 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1858 v_client = new VamsasApplication(this);
1859 setupVamsasConnectedGui();
1860 v_client.initial_update(); // TODO: thread ?
1864 // store current data in session.
1865 v_client.push_update(); // TODO: thread
1869 protected void setupVamsasConnectedGui()
1871 vamsasStart.setText(MessageManager.getString("label.session_update"));
1872 vamsasSave.setVisible(true);
1873 vamsasStop.setVisible(true);
1874 vamsasImport.setVisible(false); // Document import to existing session is
1875 // not possible for vamsas-client-1.0.
1878 protected void setupVamsasDisconnectedGui()
1880 vamsasSave.setVisible(false);
1881 vamsasStop.setVisible(false);
1882 vamsasImport.setVisible(true);
1883 vamsasStart.setText(MessageManager.getString("label.new_vamsas_session"));
1886 public void vamsasStop_actionPerformed(ActionEvent e)
1888 if (v_client != null)
1890 v_client.end_session();
1892 setupVamsasDisconnectedGui();
1896 protected void buildVamsasStMenu()
1898 if (v_client == null)
1900 String[] sess = null;
1903 sess = VamsasApplication.getSessionList();
1904 } catch (Exception e)
1906 jalview.bin.Cache.log.warn(
1907 "Problem getting current sessions list.", e);
1912 jalview.bin.Cache.log.debug("Got current sessions list: "
1913 + sess.length + " entries.");
1914 VamsasStMenu.removeAll();
1915 for (int i = 0; i < sess.length; i++)
1917 JMenuItem sessit = new JMenuItem();
1918 sessit.setText(sess[i]);
1919 sessit.setToolTipText("Connect to session " + sess[i]);
1920 final Desktop dsktp = this;
1921 final String mysesid = sess[i];
1922 sessit.addActionListener(new ActionListener()
1925 public void actionPerformed(ActionEvent e)
1927 if (dsktp.v_client == null)
1929 Thread rthr = new Thread(new Runnable()
1934 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1935 dsktp.setupVamsasConnectedGui();
1936 dsktp.v_client.initial_update();
1944 VamsasStMenu.add(sessit);
1946 // don't show an empty menu.
1947 VamsasStMenu.setVisible(sess.length > 0);
1952 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1953 VamsasStMenu.removeAll();
1954 VamsasStMenu.setVisible(false);
1959 // Not interested in the content. Just hide ourselves.
1960 VamsasStMenu.setVisible(false);
1964 public void vamsasSave_actionPerformed(ActionEvent e)
1966 if (v_client != null)
1968 JalviewFileChooser chooser = new JalviewFileChooser(
1969 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1970 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1972 { "Vamsas Document" }, "Vamsas Document");
1974 chooser.setFileView(new JalviewFileView());
1975 chooser.setDialogTitle("Save Vamsas Document Archive");
1977 int value = chooser.showSaveDialog(this);
1979 if (value == JalviewFileChooser.APPROVE_OPTION)
1981 java.io.File choice = chooser.getSelectedFile();
1982 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1983 + choice.getName());
1984 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1985 String warnmsg = null;
1986 String warnttl = null;
1989 v_client.vclient.storeDocument(choice);
1992 warnttl = "Serious Problem saving Vamsas Document";
1993 warnmsg = ex.toString();
1994 jalview.bin.Cache.log.error("Error Whilst saving document to "
1997 } catch (Exception ex)
1999 warnttl = "Problem saving Vamsas Document.";
2000 warnmsg = ex.toString();
2001 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2005 removeProgressPanel(progpanel);
2006 if (warnmsg != null)
2008 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2010 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2016 JPanel vamUpdate = null;
2019 * hide vamsas user gui bits when a vamsas document event is being handled.
2022 * true to hide gui, false to reveal gui
2024 public void setVamsasUpdate(boolean b)
2026 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2027 + (b ? "in progress" : "finished"));
2029 if (vamUpdate != null)
2031 this.removeProgressPanel(vamUpdate);
2035 vamUpdate = this.addProgressPanel("Updating vamsas session");
2037 vamsasStart.setVisible(!b);
2038 vamsasStop.setVisible(!b);
2039 vamsasSave.setVisible(!b);
2042 public JInternalFrame[] getAllFrames()
2044 return desktop.getAllFrames();
2048 * Checks the given url to see if it gives a response indicating that the user
2049 * should be informed of a new questionnaire.
2053 public void checkForQuestionnaire(String url)
2055 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2056 // javax.swing.SwingUtilities.invokeLater(jvq);
2057 new Thread(jvq).start();
2061 * Proxy class for JDesktopPane which optionally displays the current memory
2062 * usage and highlights the desktop area with a red bar if free memory runs
2067 public class MyDesktopPane extends JDesktopPane implements Runnable
2070 boolean showMemoryUsage = false;
2074 java.text.NumberFormat df;
2076 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2079 public MyDesktopPane(boolean showMemoryUsage)
2081 showMemoryUsage(showMemoryUsage);
2084 public void showMemoryUsage(boolean showMemoryUsage)
2086 this.showMemoryUsage = showMemoryUsage;
2087 if (showMemoryUsage)
2089 Thread worker = new Thread(this);
2094 public boolean isShowMemoryUsage()
2096 return showMemoryUsage;
2101 df = java.text.NumberFormat.getNumberInstance();
2102 df.setMaximumFractionDigits(2);
2103 runtime = Runtime.getRuntime();
2105 while (showMemoryUsage)
2109 maxMemory = runtime.maxMemory() / 1048576f;
2110 allocatedMemory = runtime.totalMemory() / 1048576f;
2111 freeMemory = runtime.freeMemory() / 1048576f;
2112 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2114 percentUsage = (totalFreeMemory / maxMemory) * 100;
2116 // if (percentUsage < 20)
2118 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2120 // instance.set.setBorder(border1);
2123 // sleep after showing usage
2125 } catch (Exception ex)
2127 ex.printStackTrace();
2132 public void paintComponent(Graphics g)
2134 if (showMemoryUsage && g != null && df != null)
2136 if (percentUsage < 20)
2137 g.setColor(Color.red);
2138 FontMetrics fm = g.getFontMetrics();
2142 MessageManager.formatMessage("label.memory_stats", new String[]{df.format(totalFreeMemory),df.format(maxMemory),df.format(percentUsage)}), 10,
2143 getHeight() - fm.getHeight());
2150 * fixes stacking order after a modal dialog to ensure windows that should be
2151 * on top actually are
2153 public void relayerWindows()
2158 protected JMenuItem groovyShell;
2160 public void doGroovyCheck()
2162 if (jalview.bin.Cache.groovyJarsPresent())
2164 groovyShell = new JMenuItem();
2165 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2166 groovyShell.addActionListener(new ActionListener()
2168 public void actionPerformed(ActionEvent e)
2170 groovyShell_actionPerformed(e);
2173 toolsMenu.add(groovyShell);
2174 groovyShell.setVisible(true);
2179 * Accessor method to quickly get all the AlignmentFrames loaded.
2181 public static AlignFrame[] getAlignframes()
2183 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2189 Vector avp = new Vector();
2193 for (int i = frames.length - 1; i > -1; i--)
2195 if (frames[i] instanceof AlignFrame)
2197 AlignFrame af = (AlignFrame) frames[i];
2201 } catch (Exception ex)
2203 ex.printStackTrace();
2205 if (avp.size() == 0)
2209 AlignFrame afs[] = new AlignFrame[avp.size()];
2210 for (int i = 0, j = avp.size(); i < j; i++)
2212 afs[i] = (AlignFrame) avp.elementAt(i);
2218 public AppJmol[] getJmols()
2220 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2226 Vector avp = new Vector();
2230 for (int i = frames.length - 1; i > -1; i--)
2232 if (frames[i] instanceof AppJmol)
2234 AppJmol af = (AppJmol) frames[i];
2238 } catch (Exception ex)
2240 ex.printStackTrace();
2242 if (avp.size() == 0)
2246 AppJmol afs[] = new AppJmol[avp.size()];
2247 for (int i = 0, j = avp.size(); i < j; i++)
2249 afs[i] = (AppJmol) avp.elementAt(i);
2256 * Add Groovy Support to Jalview
2258 public void groovyShell_actionPerformed(ActionEvent e)
2260 // use reflection to avoid creating compilation dependency.
2261 if (!jalview.bin.Cache.groovyJarsPresent())
2264 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2268 Class gcClass = Desktop.class.getClassLoader().loadClass(
2269 "groovy.ui.Console");
2270 Constructor gccons = gcClass.getConstructor(null);
2271 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2273 { String.class, Object.class });
2274 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2275 Object gc = gccons.newInstance(null);
2276 setvar.invoke(gc, new Object[]
2277 { "Jalview", this });
2278 run.invoke(gc, null);
2279 } catch (Exception ex)
2281 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2283 .showInternalMessageDialog(
2286 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2287 "Jalview Groovy Support Failed",
2288 JOptionPane.ERROR_MESSAGE);
2293 * Progress bars managed by the IProgressIndicator method.
2295 private Hashtable<Long, JPanel> progressBars;
2297 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2302 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2304 public void setProgressBar(String message, long id)
2306 if (progressBars == null)
2308 progressBars = new Hashtable<Long, JPanel>();
2309 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2312 if (progressBars.get(new Long(id)) != null)
2314 JPanel progressPanel = progressBars.remove(new Long(id));
2315 if (progressBarHandlers.contains(new Long(id)))
2317 progressBarHandlers.remove(new Long(id));
2319 removeProgressPanel(progressPanel);
2323 progressBars.put(new Long(id), addProgressPanel(message));
2330 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2331 * jalview.gui.IProgressIndicatorHandler)
2333 public void registerHandler(final long id,
2334 final IProgressIndicatorHandler handler)
2336 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2339 "call setProgressBar before registering the progress bar's handler.");
2341 progressBarHandlers.put(new Long(id), handler);
2342 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2343 if (handler.canCancel())
2345 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
2346 final IProgressIndicator us = this;
2347 cancel.addActionListener(new ActionListener()
2350 public void actionPerformed(ActionEvent e)
2352 handler.cancelActivity(id);
2355 + ((JLabel) progressPanel.getComponent(0))
2359 progressPanel.add(cancel, BorderLayout.EAST);
2365 * @return true if any progress bars are still active
2368 public boolean operationInProgress()
2370 if (progressBars != null && progressBars.size() > 0)
2378 * This will return the first AlignFrame viewing AlignViewport av. It will
2379 * break if there are more than one AlignFrames viewing a particular av. This
2382 * @return alignFrame for av
2384 public static AlignFrame getAlignFrameFor(AlignViewport av)
2386 if (desktop != null)
2388 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2389 for (int panel = 0; aps != null && panel < aps.length; panel++)
2391 if (aps[panel] != null && aps[panel].av == av)
2393 return aps[panel].alignFrame;
2400 public VamsasApplication getVamsasApplication()
2407 * flag set if jalview GUI is being operated programmatically
2409 private boolean inBatchMode = false;
2412 * check if jalview GUI is being operated programmatically
2414 * @return inBatchMode
2416 public boolean isInBatchMode()
2422 * set flag if jalview GUI is being operated programmatically
2424 * @param inBatchMode
2426 public void setInBatchMode(boolean inBatchMode)
2428 this.inBatchMode = inBatchMode;
2431 public void startServiceDiscovery()
2433 startServiceDiscovery(false);
2436 public void startServiceDiscovery(boolean blocking)
2438 boolean alive = true;
2439 Thread t0 = null, t1 = null, t2 = null;
2440 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2443 // todo: changesupport handlers need to be transferred
2444 if (discoverer == null)
2446 discoverer = new jalview.ws.jws1.Discoverer();
2447 // register PCS handler for desktop.
2448 discoverer.addPropertyChangeListener(changeSupport);
2450 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2451 // until we phase out completely
2452 (t0 = new Thread(discoverer)).start();
2455 // ENFIN services are EOLed as of Jalview 2.8.1 release
2460 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2462 // EnfinEnvision web service menu entries are rebuild every time the
2463 // menu is shown, so no changeSupport events are needed.
2464 jalview.ws.EnfinEnvision2OneWay.getInstance();
2465 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2468 } catch (Exception e)
2471 .info("Exception when trying to launch Envision2 workflow discovery.",
2473 Cache.log.info(e.getStackTrace());
2477 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2479 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2481 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2483 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2489 // TODO: do rest service discovery
2498 } catch (Exception e)
2501 alive = (t1 != null && t1.isAlive())
2502 || (t2 != null && t2.isAlive())
2503 || (t3 != null && t3.isAlive())
2504 || (t0 != null && t0.isAlive());
2510 * called to check if the service discovery process completed successfully.
2514 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2516 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2518 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2519 .getErrorMessages();
2522 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2524 if (serviceChangedDialog == null)
2526 // only run if we aren't already displaying one of these.
2527 addDialogThread(serviceChangedDialog = new Runnable()
2533 * JalviewDialog jd =new JalviewDialog() {
2535 * @Override protected void cancelPressed() { // TODO
2536 * Auto-generated method stub
2538 * }@Override protected void okPressed() { // TODO
2539 * Auto-generated method stub
2541 * }@Override protected void raiseClosed() { // TODO
2542 * Auto-generated method stub
2544 * } }; jd.initDialogFrame(new
2545 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2546 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2547 * + " or mis-configured HTTP proxy settings.<br/>" +
2548 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2550 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2551 * ), true, true, "Web Service Configuration Problem", 450,
2554 * jd.waitForInput();
2560 "<html><table width=\"450\"><tr><td>"
2562 + "</td></tr></table>"
2563 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2564 + " or mis-configured HTTP proxy settings.</p>"
2565 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2566 + " Tools->Preferences dialog box to change them.</p></html>"),
2567 "Web Service Configuration Problem",
2568 JOptionPane.DEFAULT_OPTION,
2569 JOptionPane.ERROR_MESSAGE);
2570 serviceChangedDialog = null;
2579 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2586 private Runnable serviceChangedDialog = null;
2589 * start a thread to open a URL in the configured browser. Pops up a warning
2590 * dialog to the user if there is an exception when calling out to the browser
2595 public static void showUrl(final String url)
2597 showUrl(url, Desktop.instance);
2601 * Like showUrl but allows progress handler to be specified
2605 * (null) or object implementing IProgressIndicator
2607 public static void showUrl(final String url,
2608 final IProgressIndicator progress)
2610 new Thread(new Runnable()
2616 if (progress != null)
2618 progress.setProgressBar("Opening " + url, this.hashCode());
2620 jalview.util.BrowserLauncher.openURL(url);
2621 } catch (Exception ex)
2624 .showInternalMessageDialog(
2626 "Unixers: Couldn't find default web browser."
2627 + "\nAdd the full path to your browser in Preferences.",
2628 "Web browser not found",
2629 JOptionPane.WARNING_MESSAGE);
2631 ex.printStackTrace();
2633 if (progress != null)
2635 progress.setProgressBar(null, this.hashCode());
2641 public static WsParamSetManager wsparamManager = null;
2643 public static ParamManager getUserParameterStore()
2645 if (wsparamManager == null)
2647 wsparamManager = new WsParamSetManager();
2649 return wsparamManager;
2653 * static hyperlink handler proxy method for use by Jalview's internal windows
2657 public static void hyperlinkUpdate(HyperlinkEvent e)
2659 if (e.getEventType() == EventType.ACTIVATED)
2664 url = e.getURL().toString();
2665 Desktop.showUrl(url);
2666 } catch (Exception x)
2670 if (Cache.log != null)
2672 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2676 System.err.println("Couldn't handle string " + url
2680 // ignore any exceptions due to dud links.
2687 * single thread that handles display of dialogs to user.
2689 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2692 * flag indicating if dialogExecutor should try to acquire a permit
2694 private volatile boolean dialogPause = true;
2699 private java.util.concurrent.Semaphore block = new Semaphore(0);
2702 * add another dialog thread to the queue
2706 public void addDialogThread(final Runnable prompter)
2708 dialogExecutor.submit(new Runnable()
2717 } catch (InterruptedException x)
2722 if (instance == null)
2728 SwingUtilities.invokeAndWait(prompter);
2729 } catch (Exception q)
2731 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2737 public void startDialogQueue()
2739 // set the flag so we don't pause waiting for another permit and semaphore
2740 // the current task to begin
2741 dialogPause = false;