2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.bin.Cache;
24 import jalview.io.FileLoader;
25 import jalview.io.FormatAdapter;
26 import jalview.io.IdentifyFile;
27 import jalview.io.JalviewFileChooser;
28 import jalview.io.JalviewFileView;
29 import jalview.util.MessageManager;
30 import jalview.ws.params.ParamManager;
32 import java.awt.BorderLayout;
33 import java.awt.Color;
34 import java.awt.Dimension;
35 import java.awt.FontMetrics;
36 import java.awt.Graphics;
37 import java.awt.GridLayout;
38 import java.awt.Point;
39 import java.awt.Rectangle;
40 import java.awt.Toolkit;
41 import java.awt.datatransfer.Clipboard;
42 import java.awt.datatransfer.ClipboardOwner;
43 import java.awt.datatransfer.DataFlavor;
44 import java.awt.datatransfer.Transferable;
45 import java.awt.dnd.DnDConstants;
46 import java.awt.dnd.DropTargetDragEvent;
47 import java.awt.dnd.DropTargetDropEvent;
48 import java.awt.dnd.DropTargetEvent;
49 import java.awt.dnd.DropTargetListener;
50 import java.awt.event.ActionEvent;
51 import java.awt.event.ActionListener;
52 import java.awt.event.FocusEvent;
53 import java.awt.event.FocusListener;
54 import java.awt.event.MouseAdapter;
55 import java.awt.event.MouseEvent;
56 import java.awt.event.MouseListener;
57 import java.awt.event.WindowAdapter;
58 import java.awt.event.WindowEvent;
59 import java.beans.PropertyChangeEvent;
60 import java.beans.PropertyChangeListener;
61 import java.beans.PropertyVetoException;
62 import java.io.BufferedInputStream;
64 import java.io.FileOutputStream;
65 import java.lang.reflect.Constructor;
67 import java.util.ArrayList;
68 import java.util.Hashtable;
69 import java.util.StringTokenizer;
70 import java.util.Vector;
71 import java.util.concurrent.ExecutorService;
72 import java.util.concurrent.Executors;
73 import java.util.concurrent.Semaphore;
75 import javax.swing.DefaultDesktopManager;
76 import javax.swing.DesktopManager;
77 import javax.swing.JButton;
78 import javax.swing.JComboBox;
79 import javax.swing.JComponent;
80 import javax.swing.JDesktopPane;
81 import javax.swing.JFrame;
82 import javax.swing.JInternalFrame;
83 import javax.swing.JLabel;
84 import javax.swing.JMenuItem;
85 import javax.swing.JOptionPane;
86 import javax.swing.JPanel;
87 import javax.swing.JPopupMenu;
88 import javax.swing.JProgressBar;
89 import javax.swing.SwingUtilities;
90 import javax.swing.event.HyperlinkEvent;
91 import javax.swing.event.MenuEvent;
92 import javax.swing.event.MenuListener;
93 import javax.swing.event.HyperlinkEvent.EventType;
100 * @version $Revision: 1.155 $
102 public class Desktop extends jalview.jbgui.GDesktop implements
103 DropTargetListener, ClipboardOwner, IProgressIndicator,
104 jalview.api.StructureSelectionManagerProvider
107 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
110 * news reader - null if it was never started.
112 private BlogReader jvnews = null;
116 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
118 public void addJalviewPropertyChangeListener(
119 PropertyChangeListener listener)
121 changeSupport.addJalviewPropertyChangeListener(listener);
125 * @param propertyName
127 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
128 * java.beans.PropertyChangeListener)
130 public void addJalviewPropertyChangeListener(String propertyName,
131 PropertyChangeListener listener)
133 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
137 * @param propertyName
139 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
140 * java.beans.PropertyChangeListener)
142 public void removeJalviewPropertyChangeListener(String propertyName,
143 PropertyChangeListener listener)
145 changeSupport.removeJalviewPropertyChangeListener(propertyName,
149 /** Singleton Desktop instance */
150 public static Desktop instance;
152 public static MyDesktopPane desktop;
154 static int openFrameCount = 0;
156 static final int xOffset = 30;
158 static final int yOffset = 30;
160 public static jalview.ws.jws1.Discoverer discoverer;
162 public static Object[] jalviewClipboard;
164 public static boolean internalCopy = false;
166 static int fileLoadingCount = 0;
168 class MyDesktopManager implements DesktopManager
171 private DesktopManager delegate;
173 public MyDesktopManager(DesktopManager delegate)
175 this.delegate = delegate;
178 public void activateFrame(JInternalFrame f)
182 delegate.activateFrame(f);
183 } catch (NullPointerException npe)
185 Point p = getMousePosition();
186 instance.showPasteMenu(p.x, p.y);
190 public void beginDraggingFrame(JComponent f)
192 delegate.beginDraggingFrame(f);
195 public void beginResizingFrame(JComponent f, int direction)
197 delegate.beginResizingFrame(f, direction);
200 public void closeFrame(JInternalFrame f)
202 delegate.closeFrame(f);
205 public void deactivateFrame(JInternalFrame f)
207 delegate.deactivateFrame(f);
210 public void deiconifyFrame(JInternalFrame f)
212 delegate.deiconifyFrame(f);
215 public void dragFrame(JComponent f, int newX, int newY)
221 delegate.dragFrame(f, newX, newY);
224 public void endDraggingFrame(JComponent f)
226 delegate.endDraggingFrame(f);
229 public void endResizingFrame(JComponent f)
231 delegate.endResizingFrame(f);
234 public void iconifyFrame(JInternalFrame f)
236 delegate.iconifyFrame(f);
239 public void maximizeFrame(JInternalFrame f)
241 delegate.maximizeFrame(f);
244 public void minimizeFrame(JInternalFrame f)
246 delegate.minimizeFrame(f);
249 public void openFrame(JInternalFrame f)
251 delegate.openFrame(f);
254 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
257 Rectangle b = desktop.getBounds();
262 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
265 public void setBoundsForFrame(JComponent f, int newX, int newY,
266 int newWidth, int newHeight)
268 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
271 // All other methods, simply delegate
276 * Creates a new Desktop object.
281 * A note to implementors. It is ESSENTIAL that any activities that might
282 * block are spawned off as threads rather than waited for during this
286 doVamsasClientCheck();
289 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
290 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
291 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
293 boolean showjconsole = jalview.bin.Cache.getDefault(
294 "SHOW_JAVA_CONSOLE", false);
295 desktop = new MyDesktopPane(selmemusage);
296 showMemusage.setSelected(selmemusage);
297 desktop.setBackground(Color.white);
298 getContentPane().setLayout(new BorderLayout());
299 // alternate config - have scrollbars - see notes in JAL-153
300 // JScrollPane sp = new JScrollPane();
301 // sp.getViewport().setView(desktop);
302 // getContentPane().add(sp, BorderLayout.CENTER);
303 getContentPane().add(desktop, BorderLayout.CENTER);
304 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
306 // This line prevents Windows Look&Feel resizing all new windows to maximum
307 // if previous window was maximised
308 desktop.setDesktopManager(new MyDesktopManager(
309 new DefaultDesktopManager()));
311 Rectangle dims = getLastKnownDimensions("");
318 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
319 setBounds((int) (screenSize.width - 900) / 2,
320 (int) (screenSize.height - 650) / 2, 900, 650);
322 jconsole = new Console(this, showjconsole);
323 // add essential build information
324 jconsole.setHeader("Jalview Desktop "
325 + jalview.bin.Cache.getProperty("VERSION") + "\n"
327 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
328 + "Java version: " + System.getProperty("java.version") + "\n"
329 + System.getProperty("os.arch") + " "
330 + System.getProperty("os.name") + " "
331 + System.getProperty("os.version"));
333 showConsole(showjconsole);
335 showNews.setVisible(false);
337 this.addWindowListener(new WindowAdapter()
339 public void windowClosing(WindowEvent evt)
346 this.addMouseListener(ma = new MouseAdapter()
348 public void mousePressed(MouseEvent evt)
350 if (SwingUtilities.isRightMouseButton(evt))
352 showPasteMenu(evt.getX(), evt.getY());
356 desktop.addMouseListener(ma);
358 this.addFocusListener(new FocusListener()
362 public void focusLost(FocusEvent e)
364 // TODO Auto-generated method stub
369 public void focusGained(FocusEvent e)
371 Cache.log.debug("Relaying windows after focus gain");
372 // make sure that we sort windows properly after we gain focus
373 instance.relayerWindows();
376 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
377 // Spawn a thread that shows the splashscreen
378 SwingUtilities.invokeLater(new Runnable()
387 // Thread off a new instance of the file chooser - this reduces the time it
388 // takes to open it later on.
389 new Thread(new Runnable()
393 Cache.log.debug("Filechooser init thread started.");
394 JalviewFileChooser chooser = new JalviewFileChooser(
395 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
396 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
397 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
398 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
399 Cache.log.debug("Filechooser init thread finished.");
402 // Add the service change listener
403 changeSupport.addJalviewPropertyChangeListener("services",
404 new PropertyChangeListener()
408 public void propertyChange(PropertyChangeEvent evt)
410 Cache.log.debug("Firing service changed event for "
411 + evt.getNewValue());
412 JalviewServicesChanged(evt);
418 public void checkForNews()
420 final Desktop me = this;
421 // Thread off the news reader, in case there are connection problems.
422 addDialogThread(new Runnable()
427 Cache.log.debug("Starting news thread.");
429 jvnews = new BlogReader(me);
430 showNews.setVisible(true);
431 Cache.log.debug("Completed news thread.");
436 protected void showNews_actionPerformed(ActionEvent e)
438 showNews(showNews.isSelected());
441 void showNews(boolean visible)
444 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
445 showNews.setSelected(visible);
446 if (visible && !jvnews.isVisible())
448 new Thread(new Runnable()
453 long instance = System.currentTimeMillis();
454 Desktop.instance.setProgressBar("Refreshing news", instance);
455 jvnews.refreshNews();
456 Desktop.instance.setProgressBar(null, instance);
465 * recover the last known dimensions for a jalview window
468 * - empty string is desktop, all other windows have unique prefix
469 * @return null or last known dimensions scaled to current geometry (if last
470 * window geom was known)
472 Rectangle getLastKnownDimensions(String windowName)
474 // TODO: lock aspect ratio for scaling desktop Bug #0058199
475 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
476 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
477 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
478 String width = jalview.bin.Cache.getProperty(windowName
480 String height = jalview.bin.Cache.getProperty(windowName
482 if ((x != null) && (y != null) && (width != null) && (height != null))
484 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
485 .parseInt(width), ih = Integer.parseInt(height);
486 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
488 // attempt #1 - try to cope with change in screen geometry - this
489 // version doesn't preserve original jv aspect ratio.
490 // take ratio of current screen size vs original screen size.
491 double sw = ((1f * screenSize.width) / (1f * Integer
492 .parseInt(jalview.bin.Cache
493 .getProperty("SCREENGEOMETRY_WIDTH"))));
494 double sh = ((1f * screenSize.height) / (1f * Integer
495 .parseInt(jalview.bin.Cache
496 .getProperty("SCREENGEOMETRY_HEIGHT"))));
497 // rescale the bounds depending upon the current screen geometry.
498 ix = (int) (ix * sw);
499 iw = (int) (iw * sw);
500 iy = (int) (iy * sh);
501 ih = (int) (ih * sh);
502 while (ix >= screenSize.width)
504 jalview.bin.Cache.log
505 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
506 ix -= screenSize.width;
508 while (iy >= screenSize.height)
510 jalview.bin.Cache.log
511 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
512 iy -= screenSize.height;
514 jalview.bin.Cache.log.debug("Got last known dimensions for "
515 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
518 // return dimensions for new instance
519 return new Rectangle(ix, iy, iw, ih);
524 private void doVamsasClientCheck()
526 if (jalview.bin.Cache.vamsasJarsPresent())
528 setupVamsasDisconnectedGui();
529 VamsasMenu.setVisible(true);
530 final Desktop us = this;
531 VamsasMenu.addMenuListener(new MenuListener()
533 // this listener remembers when the menu was first selected, and
534 // doesn't rebuild the session list until it has been cleared and
536 boolean refresh = true;
538 public void menuCanceled(MenuEvent e)
543 public void menuDeselected(MenuEvent e)
548 public void menuSelected(MenuEvent e)
552 us.buildVamsasStMenu();
557 vamsasStart.setVisible(true);
561 void showPasteMenu(int x, int y)
563 JPopupMenu popup = new JPopupMenu();
564 JMenuItem item = new JMenuItem(
565 MessageManager.getString("label.paste_new_window"));
566 item.addActionListener(new ActionListener()
568 public void actionPerformed(ActionEvent evt)
575 popup.show(this, x, y);
582 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
583 Transferable contents = c.getContents(this);
585 if (contents != null)
587 String file = (String) contents
588 .getTransferData(DataFlavor.stringFlavor);
590 String format = new IdentifyFile().Identify(file,
591 FormatAdapter.PASTE);
593 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
596 } catch (Exception ex)
599 .println("Unable to paste alignment from system clipboard:\n"
605 * Adds and opens the given frame to the desktop
616 public static synchronized void addInternalFrame(
617 final JInternalFrame frame, String title, int w, int h)
619 addInternalFrame(frame, title, w, h, true);
636 public static synchronized void addInternalFrame(
637 final JInternalFrame frame, String title, int w, int h,
641 // TODO: allow callers to determine X and Y position of frame (eg. via
643 // TODO: consider fixing method to update entries in the window submenu with
644 // the current window title
646 frame.setTitle(title);
647 if (frame.getWidth() < 1 || frame.getHeight() < 1)
651 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
652 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
653 // IF JALVIEW IS RUNNING HEADLESS
654 // ///////////////////////////////////////////////
656 || (System.getProperty("java.awt.headless") != null && System
657 .getProperty("java.awt.headless").equals("true")))
664 frame.setVisible(true);
665 frame.setClosable(true);
666 frame.setResizable(resizable);
667 frame.setMaximizable(resizable);
668 frame.setIconifiable(resizable);
669 frame.setFrameIcon(null);
671 if (frame.getX() < 1 && frame.getY() < 1)
673 frame.setLocation(xOffset * openFrameCount, yOffset
674 * ((openFrameCount - 1) % 10) + yOffset);
677 final JMenuItem menuItem = new JMenuItem(title);
678 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
680 public void internalFrameActivated(
681 javax.swing.event.InternalFrameEvent evt)
683 JInternalFrame itf = desktop.getSelectedFrame();
691 public void internalFrameClosed(
692 javax.swing.event.InternalFrameEvent evt)
694 PaintRefresher.RemoveComponent(frame);
696 windowMenu.remove(menuItem);
697 JInternalFrame itf = desktop.getSelectedFrame();
706 menuItem.addActionListener(new ActionListener()
708 public void actionPerformed(ActionEvent e)
712 frame.setSelected(true);
713 frame.setIcon(false);
714 } catch (java.beans.PropertyVetoException ex)
720 menuItem.addMouseListener(new MouseListener()
724 public void mouseReleased(MouseEvent e)
729 public void mousePressed(MouseEvent e)
734 public void mouseExited(MouseEvent e)
738 frame.setSelected(false);
739 } catch (PropertyVetoException e1)
745 public void mouseEntered(MouseEvent e)
749 frame.setSelected(true);
750 } catch (PropertyVetoException e1)
756 public void mouseClicked(MouseEvent e)
762 windowMenu.add(menuItem);
768 frame.setSelected(true);
769 frame.requestFocus();
770 } catch (java.beans.PropertyVetoException ve)
772 } catch (java.lang.ClassCastException cex)
775 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
780 public void lostOwnership(Clipboard clipboard, Transferable contents)
784 Desktop.jalviewClipboard = null;
787 internalCopy = false;
790 public void dragEnter(DropTargetDragEvent evt)
794 public void dragExit(DropTargetEvent evt)
798 public void dragOver(DropTargetDragEvent evt)
802 public void dropActionChanged(DropTargetDragEvent evt)
812 public void drop(DropTargetDropEvent evt)
814 boolean success = true;
815 Transferable t = evt.getTransferable();
816 java.util.List files = null;
817 java.util.List protocols = null;
821 DataFlavor uriListFlavor = new DataFlavor(
822 "text/uri-list;class=java.lang.String");
823 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
825 // Works on Windows and MacOSX
826 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
827 files = (java.util.List) t
828 .getTransferData(DataFlavor.javaFileListFlavor);
830 else if (t.isDataFlavorSupported(uriListFlavor))
832 // This is used by Unix drag system
833 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
834 String data = (String) t.getTransferData(uriListFlavor);
835 files = new java.util.ArrayList(1);
836 protocols = new java.util.ArrayList(1);
837 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
838 data, "\r\n"); st.hasMoreTokens();)
840 String s = st.nextToken();
841 if (s.startsWith("#"))
843 // the line is a comment (as per the RFC 2483)
846 java.net.URI uri = new java.net.URI(s);
847 if (uri.getScheme().toLowerCase().startsWith("http"))
849 protocols.add(FormatAdapter.URL);
850 files.add(uri.toString());
854 // otherwise preserve old behaviour: catch all for file objects
855 java.io.File file = new java.io.File(uri);
856 protocols.add(FormatAdapter.FILE);
857 files.add(file.toString());
861 } catch (Exception e)
870 for (int i = 0; i < files.size(); i++)
872 String file = files.get(i).toString();
873 String protocol = (protocols == null) ? FormatAdapter.FILE
874 : (String) protocols.get(i);
875 String format = null;
877 if (file.endsWith(".jar"))
884 format = new IdentifyFile().Identify(file, protocol);
887 new FileLoader().LoadFile(file, protocol, format);
890 } catch (Exception ex)
895 evt.dropComplete(success); // need this to ensure input focus is properly
896 // transfered to any new windows created
905 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
907 JalviewFileChooser chooser = new JalviewFileChooser(
908 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
909 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
910 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
911 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
913 chooser.setFileView(new JalviewFileView());
914 chooser.setDialogTitle(MessageManager
915 .getString("label.open_local_file"));
916 chooser.setToolTipText(MessageManager.getString("action.open"));
918 int value = chooser.showOpenDialog(this);
920 if (value == JalviewFileChooser.APPROVE_OPTION)
922 String choice = chooser.getSelectedFile().getPath();
923 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
924 .getSelectedFile().getParent());
926 String format = null;
927 if (chooser.getSelectedFormat() != null
928 && chooser.getSelectedFormat().equals("Jalview"))
934 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
937 if (viewport != null)
939 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
944 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
955 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
957 // This construct allows us to have a wider textfield
959 JLabel label = new JLabel(
960 MessageManager.getString("label.input_file_url"));
961 final JComboBox history = new JComboBox();
963 JPanel panel = new JPanel(new GridLayout(2, 1));
966 history.setPreferredSize(new Dimension(400, 20));
967 history.setEditable(true);
968 history.addItem("http://www.");
970 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
974 if (historyItems != null)
976 st = new StringTokenizer(historyItems, "\t");
978 while (st.hasMoreTokens())
980 history.addItem(st.nextElement());
984 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
985 MessageManager.getString("label.input_alignment_from_url"),
986 JOptionPane.OK_CANCEL_OPTION);
988 if (reply != JOptionPane.OK_OPTION)
993 String url = history.getSelectedItem().toString();
995 if (url.toLowerCase().endsWith(".jar"))
997 if (viewport != null)
999 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1004 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1009 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1011 if (format.equals("URL NOT FOUND"))
1013 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1014 "Couldn't locate " + url, "URL not found",
1015 JOptionPane.WARNING_MESSAGE);
1020 if (viewport != null)
1022 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1026 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1037 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1039 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1040 cap.setForInput(viewport);
1041 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1049 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1051 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1052 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1054 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1055 getBounds().y, getWidth(), getHeight()));
1057 if (jconsole != null)
1059 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1060 jconsole.stopConsole();
1064 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1067 if (dialogExecutor != null)
1069 dialogExecutor.shutdownNow();
1075 private void storeLastKnownDimensions(String string, Rectangle jc)
1077 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1078 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1079 + " height:" + jc.height);
1081 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1082 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1083 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1084 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1093 public void aboutMenuItem_actionPerformed(ActionEvent e)
1095 // StringBuffer message = getAboutMessage(false);
1096 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1098 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1099 new Thread(new Runnable()
1103 new SplashScreen(true);
1108 public StringBuffer getAboutMessage(boolean shortv)
1110 StringBuffer message = new StringBuffer();
1111 message.append("<html>");
1114 message.append("<h1><strong>Version: "
1115 + jalview.bin.Cache.getProperty("VERSION")
1116 + "</strong></h1>");
1117 message.append("<strong>Last Updated: <em>"
1118 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1119 + "</em></strong>");
1125 message.append("<strong>Version "
1126 + jalview.bin.Cache.getProperty("VERSION")
1127 + "; last updated: "
1128 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1131 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1134 message.append("<br>...Checking latest version...</br>");
1136 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1137 .equals(jalview.bin.Cache.getProperty("VERSION")))
1139 boolean red = false;
1140 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1141 .indexOf("automated build") == -1)
1144 // Displayed when code version and jnlp version do not match and code
1145 // version is not a development build
1146 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1149 message.append("<br>!! Version "
1150 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1152 + " is available for download from "
1153 + jalview.bin.Cache.getDefault("www.jalview.org",
1154 "http://www.jalview.org") + " !!");
1157 message.append("</div>");
1160 message.append("<br>Authors: "
1164 "The Jalview Authors (See AUTHORS file for current list)")
1165 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1166 + "<br><br>For help, see the FAQ at <a href=\"http://www.jalview.org/faq\">www.jalview.org/faq</a> and/or join the jalview-discuss@jalview.org mailing list"
1167 + "<br><br>If you use Jalview, please cite:"
1168 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1169 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1170 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1181 public void documentationMenuItem_actionPerformed(ActionEvent e)
1185 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1186 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1187 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1189 javax.help.HelpBroker hb = hs.createHelpBroker();
1190 hb.setCurrentID("home");
1191 hb.setDisplayed(true);
1192 } catch (Exception ex)
1197 public void closeAll_actionPerformed(ActionEvent e)
1199 JInternalFrame[] frames = desktop.getAllFrames();
1200 for (int i = 0; i < frames.length; i++)
1204 frames[i].setClosed(true);
1205 } catch (java.beans.PropertyVetoException ex)
1209 System.out.println("ALL CLOSED");
1210 if (v_client != null)
1212 // TODO clear binding to vamsas document objects on close_all
1217 public void raiseRelated_actionPerformed(ActionEvent e)
1219 reorderAssociatedWindows(false, false);
1222 public void minimizeAssociated_actionPerformed(ActionEvent e)
1224 reorderAssociatedWindows(true, false);
1227 void closeAssociatedWindows()
1229 reorderAssociatedWindows(false, true);
1235 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1238 protected void garbageCollect_actionPerformed(ActionEvent e)
1240 // We simply collect the garbage
1241 jalview.bin.Cache.log.debug("Collecting garbage...");
1243 jalview.bin.Cache.log.debug("Finished garbage collection.");
1250 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1253 protected void showMemusage_actionPerformed(ActionEvent e)
1255 desktop.showMemoryUsage(showMemusage.isSelected());
1262 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1265 protected void showConsole_actionPerformed(ActionEvent e)
1267 showConsole(showConsole.isSelected());
1270 Console jconsole = null;
1273 * control whether the java console is visible or not
1277 void showConsole(boolean selected)
1279 showConsole.setSelected(selected);
1280 // TODO: decide if we should update properties file
1281 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1283 jconsole.setVisible(selected);
1286 void reorderAssociatedWindows(boolean minimize, boolean close)
1288 JInternalFrame[] frames = desktop.getAllFrames();
1289 if (frames == null || frames.length < 1)
1294 AlignViewport source = null, target = null;
1295 if (frames[0] instanceof AlignFrame)
1297 source = ((AlignFrame) frames[0]).getCurrentView();
1299 else if (frames[0] instanceof TreePanel)
1301 source = ((TreePanel) frames[0]).getViewPort();
1303 else if (frames[0] instanceof PCAPanel)
1305 source = ((PCAPanel) frames[0]).av;
1307 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1309 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1314 for (int i = 0; i < frames.length; i++)
1317 if (frames[i] == null)
1321 if (frames[i] instanceof AlignFrame)
1323 target = ((AlignFrame) frames[i]).getCurrentView();
1325 else if (frames[i] instanceof TreePanel)
1327 target = ((TreePanel) frames[i]).getViewPort();
1329 else if (frames[i] instanceof PCAPanel)
1331 target = ((PCAPanel) frames[i]).av;
1333 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1335 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1338 if (source == target)
1344 frames[i].setClosed(true);
1348 frames[i].setIcon(minimize);
1351 frames[i].toFront();
1355 } catch (java.beans.PropertyVetoException ex)
1369 protected void preferences_actionPerformed(ActionEvent e)
1380 public void saveState_actionPerformed(ActionEvent e)
1382 JalviewFileChooser chooser = new JalviewFileChooser(
1383 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1384 { "jvp" }, new String[]
1385 { "Jalview Project" }, "Jalview Project");
1387 chooser.setFileView(new JalviewFileView());
1388 chooser.setDialogTitle("Save State");
1390 int value = chooser.showSaveDialog(this);
1392 if (value == JalviewFileChooser.APPROVE_OPTION)
1394 final Desktop me = this;
1395 final java.io.File choice = chooser.getSelectedFile();
1396 new Thread(new Runnable()
1401 setProgressBar("Saving jalview project " + choice.getName(),
1403 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1404 choice.getParent());
1405 // TODO catch and handle errors for savestate
1406 // TODO prevent user from messing with the Desktop whilst we're saving
1409 new Jalview2XML().SaveState(choice);
1410 } catch (OutOfMemoryError oom)
1412 new OOMWarning("Whilst saving current state to "
1413 + choice.getName(), oom);
1414 } catch (Exception ex)
1417 "Problems whilst trying to save to " + choice.getName(),
1419 JOptionPane.showMessageDialog(
1421 "Error whilst saving current state to "
1422 + choice.getName(), "Couldn't save project",
1423 JOptionPane.WARNING_MESSAGE);
1425 setProgressBar(null, choice.hashCode());
1437 public void loadState_actionPerformed(ActionEvent e)
1439 JalviewFileChooser chooser = new JalviewFileChooser(
1440 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1441 { "jvp", "jar" }, new String[]
1442 { "Jalview Project", "Jalview Project (old)" },
1444 chooser.setFileView(new JalviewFileView());
1445 chooser.setDialogTitle("Restore state");
1447 int value = chooser.showOpenDialog(this);
1449 if (value == JalviewFileChooser.APPROVE_OPTION)
1451 final String choice = chooser.getSelectedFile().getAbsolutePath();
1452 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1453 .getSelectedFile().getParent());
1454 new Thread(new Runnable()
1458 setProgressBar("loading jalview project " + choice,
1462 new Jalview2XML().LoadJalviewAlign(choice);
1463 } catch (OutOfMemoryError oom)
1465 new OOMWarning("Whilst loading project from " + choice, oom);
1466 } catch (Exception ex)
1468 Cache.log.error("Problems whilst loading project from "
1470 JOptionPane.showMessageDialog(Desktop.desktop,
1471 "Error whilst loading project from " + choice,
1472 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1474 setProgressBar(null, choice.hashCode());
1480 public void inputSequence_actionPerformed(ActionEvent e)
1482 new SequenceFetcher(this);
1485 JPanel progressPanel;
1487 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1489 public void startLoading(final String fileName)
1491 if (fileLoadingCount == 0)
1493 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1499 private JPanel addProgressPanel(String string)
1501 if (progressPanel == null)
1503 progressPanel = new JPanel(new GridLayout(1, 1));
1504 totalProgressCount = 0;
1505 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1507 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1508 JProgressBar progressBar = new JProgressBar();
1509 progressBar.setIndeterminate(true);
1511 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1513 thisprogress.add(progressBar, BorderLayout.CENTER);
1514 progressPanel.add(thisprogress);
1515 ((GridLayout) progressPanel.getLayout())
1516 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1517 ++totalProgressCount;
1518 instance.validate();
1519 return thisprogress;
1522 int totalProgressCount = 0;
1524 private void removeProgressPanel(JPanel progbar)
1526 if (progressPanel != null)
1528 synchronized (progressPanel)
1530 progressPanel.remove(progbar);
1531 GridLayout gl = (GridLayout) progressPanel.getLayout();
1532 gl.setRows(gl.getRows() - 1);
1533 if (--totalProgressCount < 1)
1535 this.getContentPane().remove(progressPanel);
1536 progressPanel = null;
1543 public void stopLoading()
1546 if (fileLoadingCount < 1)
1548 while (fileLoadingPanels.size() > 0)
1550 removeProgressPanel(fileLoadingPanels.remove(0));
1552 fileLoadingPanels.clear();
1553 fileLoadingCount = 0;
1558 public static int getViewCount(String alignmentId)
1560 AlignViewport[] aps = getViewports(alignmentId);
1561 return (aps == null) ? 0 : aps.length;
1566 * @param alignmentId
1567 * @return all AlignmentPanels concerning the alignmentId sequence set
1569 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1572 if (Desktop.desktop == null)
1574 // no frames created and in headless mode
1575 // TODO: verify that frames are recoverable when in headless mode
1578 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1579 ArrayList aps = new ArrayList();
1580 for (int t = 0; t < frames.length; t++)
1582 if (frames[t] instanceof AlignFrame)
1584 AlignFrame af = (AlignFrame) frames[t];
1585 for (int a = 0; a < af.alignPanels.size(); a++)
1587 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1588 .elementAt(a)).av.getSequenceSetId()))
1590 aps.add(af.alignPanels.elementAt(a));
1595 if (aps.size() == 0)
1599 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1600 for (int t = 0; t < vap.length; t++)
1602 vap[t] = (AlignmentPanel) aps.get(t);
1608 * get all the viewports on an alignment.
1610 * @param sequenceSetId
1611 * unique alignment id
1612 * @return all viewports on the alignment bound to sequenceSetId
1614 public static AlignViewport[] getViewports(String sequenceSetId)
1616 Vector viewp = new Vector();
1617 if (desktop != null)
1619 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1621 for (int t = 0; t < frames.length; t++)
1623 if (frames[t] instanceof AlignFrame)
1625 AlignFrame afr = ((AlignFrame) frames[t]);
1626 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1628 if (afr.alignPanels != null)
1630 for (int a = 0; a < afr.alignPanels.size(); a++)
1632 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1633 .elementAt(a)).av.getSequenceSetId()))
1635 viewp.addElement(((AlignmentPanel) afr.alignPanels
1642 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1647 if (viewp.size() > 0)
1649 AlignViewport[] vp = new AlignViewport[viewp.size()];
1657 public void explodeViews(AlignFrame af)
1659 int size = af.alignPanels.size();
1665 for (int i = 0; i < size; i++)
1667 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1668 AlignFrame newaf = new AlignFrame(ap);
1669 if (ap.av.explodedPosition != null
1670 && !ap.av.explodedPosition.equals(af.getBounds()))
1672 newaf.setBounds(ap.av.explodedPosition);
1675 ap.av.gatherViewsHere = false;
1677 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1678 AlignFrame.DEFAULT_HEIGHT);
1681 af.alignPanels.clear();
1682 af.closeMenuItem_actionPerformed(true);
1686 public void gatherViews(AlignFrame source)
1688 source.viewport.gatherViewsHere = true;
1689 source.viewport.explodedPosition = source.getBounds();
1690 JInternalFrame[] frames = desktop.getAllFrames();
1691 String viewId = source.viewport.getSequenceSetId();
1693 for (int t = 0; t < frames.length; t++)
1695 if (frames[t] instanceof AlignFrame && frames[t] != source)
1697 AlignFrame af = (AlignFrame) frames[t];
1698 boolean gatherThis = false;
1699 for (int a = 0; a < af.alignPanels.size(); a++)
1701 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1702 if (viewId.equals(ap.av.getSequenceSetId()))
1705 ap.av.gatherViewsHere = false;
1706 ap.av.explodedPosition = af.getBounds();
1707 source.addAlignmentPanel(ap, false);
1713 af.alignPanels.clear();
1714 af.closeMenuItem_actionPerformed(true);
1721 jalview.gui.VamsasApplication v_client = null;
1723 public void vamsasImport_actionPerformed(ActionEvent e)
1725 if (v_client == null)
1727 // Load and try to start a session.
1728 JalviewFileChooser chooser = new JalviewFileChooser(
1729 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1731 chooser.setFileView(new JalviewFileView());
1732 chooser.setDialogTitle("Open a saved VAMSAS session");
1733 chooser.setToolTipText(MessageManager
1734 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1736 int value = chooser.showOpenDialog(this);
1738 if (value == JalviewFileChooser.APPROVE_OPTION)
1740 String fle = chooser.getSelectedFile().toString();
1741 if (!vamsasImport(chooser.getSelectedFile()))
1744 .showInternalMessageDialog(
1746 MessageManager.formatMessage(
1747 "label.couldnt_import_as_vamsas_session",
1751 .getString("label.vamsas_document_import_failed"),
1752 JOptionPane.ERROR_MESSAGE);
1758 jalview.bin.Cache.log
1759 .error("Implementation error - load session from a running session is not supported.");
1764 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1767 * @return true if import was a success and a session was started.
1769 public boolean vamsasImport(URL url)
1771 // TODO: create progress bar
1772 if (v_client != null)
1775 jalview.bin.Cache.log
1776 .error("Implementation error - load session from a running session is not supported.");
1782 // copy the URL content to a temporary local file
1783 // TODO: be a bit cleverer here with nio (?!)
1784 File file = File.createTempFile("vdocfromurl", ".vdj");
1785 FileOutputStream fos = new FileOutputStream(file);
1786 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1787 byte[] buffer = new byte[2048];
1789 while ((ln = bis.read(buffer)) > -1)
1791 fos.write(buffer, 0, ln);
1795 v_client = new jalview.gui.VamsasApplication(this, file,
1796 url.toExternalForm());
1797 } catch (Exception ex)
1799 jalview.bin.Cache.log.error(
1800 "Failed to create new vamsas session from contents of URL "
1804 setupVamsasConnectedGui();
1805 v_client.initial_update(); // TODO: thread ?
1806 return v_client.inSession();
1810 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1813 * @return true if import was a success and a session was started.
1815 public boolean vamsasImport(File file)
1817 if (v_client != null)
1820 jalview.bin.Cache.log
1821 .error("Implementation error - load session from a running session is not supported.");
1825 setProgressBar("Importing VAMSAS session from " + file.getName(),
1829 v_client = new jalview.gui.VamsasApplication(this, file, null);
1830 } catch (Exception ex)
1832 setProgressBar("Importing VAMSAS session from " + file.getName(),
1834 jalview.bin.Cache.log.error(
1835 "New vamsas session from existing session file failed:", ex);
1838 setupVamsasConnectedGui();
1839 v_client.initial_update(); // TODO: thread ?
1840 setProgressBar("Importing VAMSAS session from " + file.getName(),
1842 return v_client.inSession();
1845 public boolean joinVamsasSession(String mysesid)
1847 if (v_client != null)
1850 "Trying to join a vamsas session when another is already connected.");
1852 if (mysesid == null)
1854 throw new Error("Invalid vamsas session id.");
1856 v_client = new VamsasApplication(this, mysesid);
1857 setupVamsasConnectedGui();
1858 v_client.initial_update();
1859 return (v_client.inSession());
1862 public void vamsasStart_actionPerformed(ActionEvent e)
1864 if (v_client == null)
1867 // we just start a default session for moment.
1869 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1870 * getProperty("LAST_DIRECTORY"));
1872 * chooser.setFileView(new JalviewFileView());
1873 * chooser.setDialogTitle("Load Vamsas file");
1874 * chooser.setToolTipText("Import");
1876 * int value = chooser.showOpenDialog(this);
1878 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1879 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1881 v_client = new VamsasApplication(this);
1882 setupVamsasConnectedGui();
1883 v_client.initial_update(); // TODO: thread ?
1887 // store current data in session.
1888 v_client.push_update(); // TODO: thread
1892 protected void setupVamsasConnectedGui()
1894 vamsasStart.setText(MessageManager.getString("label.session_update"));
1895 vamsasSave.setVisible(true);
1896 vamsasStop.setVisible(true);
1897 vamsasImport.setVisible(false); // Document import to existing session is
1898 // not possible for vamsas-client-1.0.
1901 protected void setupVamsasDisconnectedGui()
1903 vamsasSave.setVisible(false);
1904 vamsasStop.setVisible(false);
1905 vamsasImport.setVisible(true);
1906 vamsasStart.setText(MessageManager
1907 .getString("label.new_vamsas_session"));
1910 public void vamsasStop_actionPerformed(ActionEvent e)
1912 if (v_client != null)
1914 v_client.end_session();
1916 setupVamsasDisconnectedGui();
1920 protected void buildVamsasStMenu()
1922 if (v_client == null)
1924 String[] sess = null;
1927 sess = VamsasApplication.getSessionList();
1928 } catch (Exception e)
1930 jalview.bin.Cache.log.warn(
1931 "Problem getting current sessions list.", e);
1936 jalview.bin.Cache.log.debug("Got current sessions list: "
1937 + sess.length + " entries.");
1938 VamsasStMenu.removeAll();
1939 for (int i = 0; i < sess.length; i++)
1941 JMenuItem sessit = new JMenuItem();
1942 sessit.setText(sess[i]);
1943 sessit.setToolTipText(MessageManager.formatMessage(
1944 "label.connect_to_session", new String[]
1946 final Desktop dsktp = this;
1947 final String mysesid = sess[i];
1948 sessit.addActionListener(new ActionListener()
1951 public void actionPerformed(ActionEvent e)
1953 if (dsktp.v_client == null)
1955 Thread rthr = new Thread(new Runnable()
1960 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1961 dsktp.setupVamsasConnectedGui();
1962 dsktp.v_client.initial_update();
1970 VamsasStMenu.add(sessit);
1972 // don't show an empty menu.
1973 VamsasStMenu.setVisible(sess.length > 0);
1978 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1979 VamsasStMenu.removeAll();
1980 VamsasStMenu.setVisible(false);
1985 // Not interested in the content. Just hide ourselves.
1986 VamsasStMenu.setVisible(false);
1990 public void vamsasSave_actionPerformed(ActionEvent e)
1992 if (v_client != null)
1994 JalviewFileChooser chooser = new JalviewFileChooser(
1995 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1996 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1998 { "Vamsas Document" }, "Vamsas Document");
2000 chooser.setFileView(new JalviewFileView());
2001 chooser.setDialogTitle("Save Vamsas Document Archive");
2003 int value = chooser.showSaveDialog(this);
2005 if (value == JalviewFileChooser.APPROVE_OPTION)
2007 java.io.File choice = chooser.getSelectedFile();
2008 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
2009 + choice.getName());
2010 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2011 String warnmsg = null;
2012 String warnttl = null;
2015 v_client.vclient.storeDocument(choice);
2018 warnttl = "Serious Problem saving Vamsas Document";
2019 warnmsg = ex.toString();
2020 jalview.bin.Cache.log.error("Error Whilst saving document to "
2023 } catch (Exception ex)
2025 warnttl = "Problem saving Vamsas Document.";
2026 warnmsg = ex.toString();
2027 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2031 removeProgressPanel(progpanel);
2032 if (warnmsg != null)
2034 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2036 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2042 JPanel vamUpdate = null;
2045 * hide vamsas user gui bits when a vamsas document event is being handled.
2048 * true to hide gui, false to reveal gui
2050 public void setVamsasUpdate(boolean b)
2052 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2053 + (b ? "in progress" : "finished"));
2055 if (vamUpdate != null)
2057 this.removeProgressPanel(vamUpdate);
2061 vamUpdate = this.addProgressPanel("Updating vamsas session");
2063 vamsasStart.setVisible(!b);
2064 vamsasStop.setVisible(!b);
2065 vamsasSave.setVisible(!b);
2068 public JInternalFrame[] getAllFrames()
2070 return desktop.getAllFrames();
2074 * Checks the given url to see if it gives a response indicating that the user
2075 * should be informed of a new questionnaire.
2079 public void checkForQuestionnaire(String url)
2081 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2082 // javax.swing.SwingUtilities.invokeLater(jvq);
2083 new Thread(jvq).start();
2087 * Proxy class for JDesktopPane which optionally displays the current memory
2088 * usage and highlights the desktop area with a red bar if free memory runs
2093 public class MyDesktopPane extends JDesktopPane implements Runnable
2096 boolean showMemoryUsage = false;
2100 java.text.NumberFormat df;
2102 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2105 public MyDesktopPane(boolean showMemoryUsage)
2107 showMemoryUsage(showMemoryUsage);
2110 public void showMemoryUsage(boolean showMemoryUsage)
2112 this.showMemoryUsage = showMemoryUsage;
2113 if (showMemoryUsage)
2115 Thread worker = new Thread(this);
2120 public boolean isShowMemoryUsage()
2122 return showMemoryUsage;
2127 df = java.text.NumberFormat.getNumberInstance();
2128 df.setMaximumFractionDigits(2);
2129 runtime = Runtime.getRuntime();
2131 while (showMemoryUsage)
2135 maxMemory = runtime.maxMemory() / 1048576f;
2136 allocatedMemory = runtime.totalMemory() / 1048576f;
2137 freeMemory = runtime.freeMemory() / 1048576f;
2138 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2140 percentUsage = (totalFreeMemory / maxMemory) * 100;
2142 // if (percentUsage < 20)
2144 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2146 // instance.set.setBorder(border1);
2149 // sleep after showing usage
2151 } catch (Exception ex)
2153 ex.printStackTrace();
2158 public void paintComponent(Graphics g)
2160 if (showMemoryUsage && g != null && df != null)
2162 if (percentUsage < 20)
2163 g.setColor(Color.red);
2164 FontMetrics fm = g.getFontMetrics();
2167 g.drawString(MessageManager.formatMessage(
2168 "label.memory_stats",
2170 { df.format(totalFreeMemory), df.format(maxMemory),
2171 df.format(percentUsage) }), 10,
2172 getHeight() - fm.getHeight());
2179 * fixes stacking order after a modal dialog to ensure windows that should be
2180 * on top actually are
2182 public void relayerWindows()
2187 protected JMenuItem groovyShell;
2189 public void doGroovyCheck()
2191 if (jalview.bin.Cache.groovyJarsPresent())
2193 groovyShell = new JMenuItem();
2194 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2195 groovyShell.addActionListener(new ActionListener()
2197 public void actionPerformed(ActionEvent e)
2199 groovyShell_actionPerformed(e);
2202 toolsMenu.add(groovyShell);
2203 groovyShell.setVisible(true);
2208 * Accessor method to quickly get all the AlignmentFrames loaded.
2210 public static AlignFrame[] getAlignframes()
2212 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2218 Vector avp = new Vector();
2222 for (int i = frames.length - 1; i > -1; i--)
2224 if (frames[i] instanceof AlignFrame)
2226 AlignFrame af = (AlignFrame) frames[i];
2230 } catch (Exception ex)
2232 ex.printStackTrace();
2234 if (avp.size() == 0)
2238 AlignFrame afs[] = new AlignFrame[avp.size()];
2239 for (int i = 0, j = avp.size(); i < j; i++)
2241 afs[i] = (AlignFrame) avp.elementAt(i);
2247 public AppJmol[] getJmols()
2249 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2255 Vector avp = new Vector();
2259 for (int i = frames.length - 1; i > -1; i--)
2261 if (frames[i] instanceof AppJmol)
2263 AppJmol af = (AppJmol) frames[i];
2267 } catch (Exception ex)
2269 ex.printStackTrace();
2271 if (avp.size() == 0)
2275 AppJmol afs[] = new AppJmol[avp.size()];
2276 for (int i = 0, j = avp.size(); i < j; i++)
2278 afs[i] = (AppJmol) avp.elementAt(i);
2285 * Add Groovy Support to Jalview
2287 public void groovyShell_actionPerformed(ActionEvent e)
2289 // use reflection to avoid creating compilation dependency.
2290 if (!jalview.bin.Cache.groovyJarsPresent())
2293 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2297 Class gcClass = Desktop.class.getClassLoader().loadClass(
2298 "groovy.ui.Console");
2299 Constructor gccons = gcClass.getConstructor(null);
2300 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2302 { String.class, Object.class });
2303 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2304 Object gc = gccons.newInstance(null);
2305 setvar.invoke(gc, new Object[]
2306 { "Jalview", this });
2307 run.invoke(gc, null);
2308 } catch (Exception ex)
2310 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2312 .showInternalMessageDialog(
2315 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2316 "Jalview Groovy Support Failed",
2317 JOptionPane.ERROR_MESSAGE);
2322 * Progress bars managed by the IProgressIndicator method.
2324 private Hashtable<Long, JPanel> progressBars;
2326 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2331 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2333 public void setProgressBar(String message, long id)
2335 if (progressBars == null)
2337 progressBars = new Hashtable<Long, JPanel>();
2338 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2341 if (progressBars.get(new Long(id)) != null)
2343 JPanel progressPanel = progressBars.remove(new Long(id));
2344 if (progressBarHandlers.contains(new Long(id)))
2346 progressBarHandlers.remove(new Long(id));
2348 removeProgressPanel(progressPanel);
2352 progressBars.put(new Long(id), addProgressPanel(message));
2359 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2360 * jalview.gui.IProgressIndicatorHandler)
2362 public void registerHandler(final long id,
2363 final IProgressIndicatorHandler handler)
2365 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2368 "call setProgressBar before registering the progress bar's handler.");
2370 progressBarHandlers.put(new Long(id), handler);
2371 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2372 if (handler.canCancel())
2374 JButton cancel = new JButton(
2375 MessageManager.getString("action.cancel"));
2376 final IProgressIndicator us = this;
2377 cancel.addActionListener(new ActionListener()
2380 public void actionPerformed(ActionEvent e)
2382 handler.cancelActivity(id);
2385 + ((JLabel) progressPanel.getComponent(0))
2389 progressPanel.add(cancel, BorderLayout.EAST);
2395 * @return true if any progress bars are still active
2398 public boolean operationInProgress()
2400 if (progressBars != null && progressBars.size() > 0)
2408 * This will return the first AlignFrame viewing AlignViewport av. It will
2409 * break if there are more than one AlignFrames viewing a particular av. This
2412 * @return alignFrame for av
2414 public static AlignFrame getAlignFrameFor(AlignViewport av)
2416 if (desktop != null)
2418 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2419 for (int panel = 0; aps != null && panel < aps.length; panel++)
2421 if (aps[panel] != null && aps[panel].av == av)
2423 return aps[panel].alignFrame;
2430 public VamsasApplication getVamsasApplication()
2437 * flag set if jalview GUI is being operated programmatically
2439 private boolean inBatchMode = false;
2442 * check if jalview GUI is being operated programmatically
2444 * @return inBatchMode
2446 public boolean isInBatchMode()
2452 * set flag if jalview GUI is being operated programmatically
2454 * @param inBatchMode
2456 public void setInBatchMode(boolean inBatchMode)
2458 this.inBatchMode = inBatchMode;
2461 public void startServiceDiscovery()
2463 startServiceDiscovery(false);
2466 public void startServiceDiscovery(boolean blocking)
2468 boolean alive = true;
2469 Thread t0 = null, t1 = null, t2 = null;
2470 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2473 // todo: changesupport handlers need to be transferred
2474 if (discoverer == null)
2476 discoverer = new jalview.ws.jws1.Discoverer();
2477 // register PCS handler for desktop.
2478 discoverer.addPropertyChangeListener(changeSupport);
2480 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2481 // until we phase out completely
2482 (t0 = new Thread(discoverer)).start();
2485 // ENFIN services are EOLed as of Jalview 2.8.1 release
2490 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2492 // EnfinEnvision web service menu entries are rebuild every time the
2493 // menu is shown, so no changeSupport events are needed.
2494 jalview.ws.EnfinEnvision2OneWay.getInstance();
2495 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2498 } catch (Exception e)
2501 .info("Exception when trying to launch Envision2 workflow discovery.",
2503 Cache.log.info(e.getStackTrace());
2507 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2509 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2511 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2513 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2519 // TODO: do rest service discovery
2528 } catch (Exception e)
2531 alive = (t1 != null && t1.isAlive())
2532 || (t2 != null && t2.isAlive())
2533 || (t3 != null && t3.isAlive())
2534 || (t0 != null && t0.isAlive());
2540 * called to check if the service discovery process completed successfully.
2544 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2546 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2548 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2549 .getErrorMessages();
2552 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2554 if (serviceChangedDialog == null)
2556 // only run if we aren't already displaying one of these.
2557 addDialogThread(serviceChangedDialog = new Runnable()
2563 * JalviewDialog jd =new JalviewDialog() {
2565 * @Override protected void cancelPressed() { // TODO
2566 * Auto-generated method stub
2568 * }@Override protected void okPressed() { // TODO
2569 * Auto-generated method stub
2571 * }@Override protected void raiseClosed() { // TODO
2572 * Auto-generated method stub
2574 * } }; jd.initDialogFrame(new
2575 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2576 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2577 * + " or mis-configured HTTP proxy settings.<br/>" +
2578 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2580 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2581 * ), true, true, "Web Service Configuration Problem", 450,
2584 * jd.waitForInput();
2590 "<html><table width=\"450\"><tr><td>"
2592 + "</td></tr></table>"
2593 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2594 + " or mis-configured HTTP proxy settings.</p>"
2595 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2596 + " Tools->Preferences dialog box to change them.</p></html>"),
2597 "Web Service Configuration Problem",
2598 JOptionPane.DEFAULT_OPTION,
2599 JOptionPane.ERROR_MESSAGE);
2600 serviceChangedDialog = null;
2609 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2616 private Runnable serviceChangedDialog = null;
2619 * start a thread to open a URL in the configured browser. Pops up a warning
2620 * dialog to the user if there is an exception when calling out to the browser
2625 public static void showUrl(final String url)
2627 showUrl(url, Desktop.instance);
2631 * Like showUrl but allows progress handler to be specified
2635 * (null) or object implementing IProgressIndicator
2637 public static void showUrl(final String url,
2638 final IProgressIndicator progress)
2640 new Thread(new Runnable()
2646 if (progress != null)
2648 progress.setProgressBar("Opening " + url, this.hashCode());
2650 jalview.util.BrowserLauncher.openURL(url);
2651 } catch (Exception ex)
2654 .showInternalMessageDialog(
2656 "Unixers: Couldn't find default web browser."
2657 + "\nAdd the full path to your browser in Preferences.",
2658 "Web browser not found",
2659 JOptionPane.WARNING_MESSAGE);
2661 ex.printStackTrace();
2663 if (progress != null)
2665 progress.setProgressBar(null, this.hashCode());
2671 public static WsParamSetManager wsparamManager = null;
2673 public static ParamManager getUserParameterStore()
2675 if (wsparamManager == null)
2677 wsparamManager = new WsParamSetManager();
2679 return wsparamManager;
2683 * static hyperlink handler proxy method for use by Jalview's internal windows
2687 public static void hyperlinkUpdate(HyperlinkEvent e)
2689 if (e.getEventType() == EventType.ACTIVATED)
2694 url = e.getURL().toString();
2695 Desktop.showUrl(url);
2696 } catch (Exception x)
2700 if (Cache.log != null)
2702 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2706 System.err.println("Couldn't handle string " + url
2710 // ignore any exceptions due to dud links.
2717 * single thread that handles display of dialogs to user.
2719 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2722 * flag indicating if dialogExecutor should try to acquire a permit
2724 private volatile boolean dialogPause = true;
2729 private java.util.concurrent.Semaphore block = new Semaphore(0);
2732 * add another dialog thread to the queue
2736 public void addDialogThread(final Runnable prompter)
2738 dialogExecutor.submit(new Runnable()
2747 } catch (InterruptedException x)
2752 if (instance == null)
2758 SwingUtilities.invokeAndWait(prompter);
2759 } catch (Exception q)
2761 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2767 public void startDialogQueue()
2769 // set the flag so we don't pause waiting for another permit and semaphore
2770 // the current task to begin
2771 dialogPause = false;