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(MessageManager.getString("label.paste_new_window"));
565 item.addActionListener(new ActionListener()
567 public void actionPerformed(ActionEvent evt)
574 popup.show(this, x, y);
581 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
582 Transferable contents = c.getContents(this);
584 if (contents != null)
586 String file = (String) contents
587 .getTransferData(DataFlavor.stringFlavor);
589 String format = new IdentifyFile().Identify(file,
590 FormatAdapter.PASTE);
592 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
595 } catch (Exception ex)
598 .println("Unable to paste alignment from system clipboard:\n"
604 * Adds and opens the given frame to the desktop
615 public static synchronized void addInternalFrame(
616 final JInternalFrame frame, String title, int w, int h)
618 addInternalFrame(frame, title, w, h, true);
635 public static synchronized void addInternalFrame(
636 final JInternalFrame frame, String title, int w, int h,
640 // TODO: allow callers to determine X and Y position of frame (eg. via
642 // TODO: consider fixing method to update entries in the window submenu with
643 // the current window title
645 frame.setTitle(title);
646 if (frame.getWidth() < 1 || frame.getHeight() < 1)
650 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
651 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
652 // IF JALVIEW IS RUNNING HEADLESS
653 // ///////////////////////////////////////////////
654 if (instance == null || (System.getProperty("java.awt.headless") != null
655 && System.getProperty("java.awt.headless").equals("true")))
662 frame.setVisible(true);
663 frame.setClosable(true);
664 frame.setResizable(resizable);
665 frame.setMaximizable(resizable);
666 frame.setIconifiable(resizable);
667 frame.setFrameIcon(null);
669 if (frame.getX() < 1 && frame.getY() < 1)
671 frame.setLocation(xOffset * openFrameCount, yOffset
672 * ((openFrameCount - 1) % 10) + yOffset);
675 final JMenuItem menuItem = new JMenuItem(title);
676 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
678 public void internalFrameActivated(
679 javax.swing.event.InternalFrameEvent evt)
681 JInternalFrame itf = desktop.getSelectedFrame();
689 public void internalFrameClosed(
690 javax.swing.event.InternalFrameEvent evt)
692 PaintRefresher.RemoveComponent(frame);
694 windowMenu.remove(menuItem);
695 JInternalFrame itf = desktop.getSelectedFrame();
704 menuItem.addActionListener(new ActionListener()
706 public void actionPerformed(ActionEvent e)
710 frame.setSelected(true);
711 frame.setIcon(false);
712 } catch (java.beans.PropertyVetoException ex)
718 menuItem.addMouseListener(new MouseListener()
722 public void mouseReleased(MouseEvent e)
727 public void mousePressed(MouseEvent e)
732 public void mouseExited(MouseEvent e)
736 frame.setSelected(false);
737 } catch (PropertyVetoException e1)
743 public void mouseEntered(MouseEvent e)
747 frame.setSelected(true);
748 } catch (PropertyVetoException e1)
754 public void mouseClicked(MouseEvent e)
760 windowMenu.add(menuItem);
766 frame.setSelected(true);
767 frame.requestFocus();
768 } catch (java.beans.PropertyVetoException ve)
770 } catch (java.lang.ClassCastException cex)
773 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
778 public void lostOwnership(Clipboard clipboard, Transferable contents)
782 Desktop.jalviewClipboard = null;
785 internalCopy = false;
788 public void dragEnter(DropTargetDragEvent evt)
792 public void dragExit(DropTargetEvent evt)
796 public void dragOver(DropTargetDragEvent evt)
800 public void dropActionChanged(DropTargetDragEvent evt)
810 public void drop(DropTargetDropEvent evt)
812 boolean success=true;
813 Transferable t = evt.getTransferable();
814 java.util.List files = null;
815 java.util.List protocols = null;
819 DataFlavor uriListFlavor = new DataFlavor(
820 "text/uri-list;class=java.lang.String");
821 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
823 // Works on Windows and MacOSX
824 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
825 files = (java.util.List) t
826 .getTransferData(DataFlavor.javaFileListFlavor);
828 else if (t.isDataFlavorSupported(uriListFlavor))
830 // This is used by Unix drag system
831 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
832 String data = (String) t.getTransferData(uriListFlavor);
833 files = new java.util.ArrayList(1);
834 protocols = new java.util.ArrayList(1);
835 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
836 data, "\r\n"); st.hasMoreTokens();)
838 String s = st.nextToken();
839 if (s.startsWith("#"))
841 // the line is a comment (as per the RFC 2483)
844 java.net.URI uri = new java.net.URI(s);
845 if (uri.getScheme().toLowerCase().startsWith("http"))
847 protocols.add(FormatAdapter.URL);
848 files.add(uri.toString());
852 // otherwise preserve old behaviour: catch all for file objects
853 java.io.File file = new java.io.File(uri);
854 protocols.add(FormatAdapter.FILE);
855 files.add(file.toString());
859 } catch (Exception e)
868 for (int i = 0; i < files.size(); i++)
870 String file = files.get(i).toString();
871 String protocol = (protocols == null) ? FormatAdapter.FILE
872 : (String) protocols.get(i);
873 String format = null;
875 if (file.endsWith(".jar"))
882 format = new IdentifyFile().Identify(file, protocol);
885 new FileLoader().LoadFile(file, protocol, format);
888 } catch (Exception ex)
893 evt.dropComplete(success); // need this to ensure input focus is properly transfered to any new windows created
902 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
904 JalviewFileChooser chooser = new JalviewFileChooser(
905 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
906 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
907 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
908 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
910 chooser.setFileView(new JalviewFileView());
911 chooser.setDialogTitle(MessageManager.getString("label.open_local_file"));
912 chooser.setToolTipText(MessageManager.getString("action.open"));
914 int value = chooser.showOpenDialog(this);
916 if (value == JalviewFileChooser.APPROVE_OPTION)
918 String choice = chooser.getSelectedFile().getPath();
919 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
920 .getSelectedFile().getParent());
922 String format = null;
923 if (chooser.getSelectedFormat()!=null && chooser.getSelectedFormat().equals("Jalview"))
929 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
932 if (viewport != null)
934 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
939 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
950 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
952 // This construct allows us to have a wider textfield
954 JLabel label = new JLabel(MessageManager.getString("label.input_file_url"));
955 final JComboBox history = new JComboBox();
957 JPanel panel = new JPanel(new GridLayout(2, 1));
960 history.setPreferredSize(new Dimension(400, 20));
961 history.setEditable(true);
962 history.addItem("http://www.");
964 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
968 if (historyItems != null)
970 st = new StringTokenizer(historyItems, "\t");
972 while (st.hasMoreTokens())
974 history.addItem(st.nextElement());
978 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
979 MessageManager.getString("label.input_alignment_from_url"), JOptionPane.OK_CANCEL_OPTION);
981 if (reply != JOptionPane.OK_OPTION)
986 String url = history.getSelectedItem().toString();
988 if (url.toLowerCase().endsWith(".jar"))
990 if (viewport != null)
992 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
997 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1002 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1004 if (format.equals("URL NOT FOUND"))
1006 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1007 "Couldn't locate " + url, "URL not found",
1008 JOptionPane.WARNING_MESSAGE);
1013 if (viewport != null)
1015 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1019 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1030 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1032 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1033 cap.setForInput(viewport);
1034 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1042 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1044 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1045 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1047 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1048 getBounds().y, getWidth(), getHeight()));
1050 if (jconsole != null)
1052 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1053 jconsole.stopConsole();
1057 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1060 if (dialogExecutor != null)
1062 dialogExecutor.shutdownNow();
1068 private void storeLastKnownDimensions(String string, Rectangle jc)
1070 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1071 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1072 + " height:" + jc.height);
1074 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1075 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1076 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1077 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1086 public void aboutMenuItem_actionPerformed(ActionEvent e)
1088 // StringBuffer message = getAboutMessage(false);
1089 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1091 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1092 new Thread(new Runnable()
1096 new SplashScreen(true);
1101 public StringBuffer getAboutMessage(boolean shortv)
1103 StringBuffer message = new StringBuffer();
1104 message.append("<html>");
1107 message.append("<h1><strong>Version: "
1108 + jalview.bin.Cache.getProperty("VERSION")
1109 + "</strong></h1><br>");
1110 message.append("<strong>Last Updated: <em>"
1111 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1112 + "</em></strong>");
1118 message.append("<strong>Version "
1119 + jalview.bin.Cache.getProperty("VERSION")
1120 + "; last updated: "
1121 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1124 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1127 message.append("<br>...Checking latest version...</br>");
1129 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1130 .equals(jalview.bin.Cache.getProperty("VERSION")))
1132 boolean red = false;
1133 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1134 .indexOf("automated build") == -1)
1137 // Displayed when code version and jnlp version do not match and code
1138 // version is not a development build
1139 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1142 message.append("<br>!! Version "
1143 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1145 + " is available for download from "
1146 + jalview.bin.Cache.getDefault("www.jalview.org",
1147 "http://www.jalview.org") + " !!");
1150 message.append("</div>");
1153 message.append("<br>Authors: "
1157 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1158 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1159 + "<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"
1160 + "<br>If you use Jalview, please cite:"
1161 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1162 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1163 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1174 public void documentationMenuItem_actionPerformed(ActionEvent e)
1178 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1179 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1180 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1182 javax.help.HelpBroker hb = hs.createHelpBroker();
1183 hb.setCurrentID("home");
1184 hb.setDisplayed(true);
1185 } catch (Exception ex)
1190 public void closeAll_actionPerformed(ActionEvent e)
1192 JInternalFrame[] frames = desktop.getAllFrames();
1193 for (int i = 0; i < frames.length; i++)
1197 frames[i].setClosed(true);
1198 } catch (java.beans.PropertyVetoException ex)
1202 System.out.println("ALL CLOSED");
1203 if (v_client != null)
1205 // TODO clear binding to vamsas document objects on close_all
1210 public void raiseRelated_actionPerformed(ActionEvent e)
1212 reorderAssociatedWindows(false, false);
1215 public void minimizeAssociated_actionPerformed(ActionEvent e)
1217 reorderAssociatedWindows(true, false);
1220 void closeAssociatedWindows()
1222 reorderAssociatedWindows(false, true);
1228 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1231 protected void garbageCollect_actionPerformed(ActionEvent e)
1233 // We simply collect the garbage
1234 jalview.bin.Cache.log.debug("Collecting garbage...");
1236 jalview.bin.Cache.log.debug("Finished garbage collection.");
1243 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1246 protected void showMemusage_actionPerformed(ActionEvent e)
1248 desktop.showMemoryUsage(showMemusage.isSelected());
1255 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1258 protected void showConsole_actionPerformed(ActionEvent e)
1260 showConsole(showConsole.isSelected());
1263 Console jconsole = null;
1266 * control whether the java console is visible or not
1270 void showConsole(boolean selected)
1272 showConsole.setSelected(selected);
1273 // TODO: decide if we should update properties file
1274 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1276 jconsole.setVisible(selected);
1279 void reorderAssociatedWindows(boolean minimize, boolean close)
1281 JInternalFrame[] frames = desktop.getAllFrames();
1282 if (frames == null || frames.length < 1)
1287 AlignViewport source = null, target = null;
1288 if (frames[0] instanceof AlignFrame)
1290 source = ((AlignFrame) frames[0]).getCurrentView();
1292 else if (frames[0] instanceof TreePanel)
1294 source = ((TreePanel) frames[0]).getViewPort();
1296 else if (frames[0] instanceof PCAPanel)
1298 source = ((PCAPanel) frames[0]).av;
1300 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1302 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1307 for (int i = 0; i < frames.length; i++)
1310 if (frames[i] == null)
1314 if (frames[i] instanceof AlignFrame)
1316 target = ((AlignFrame) frames[i]).getCurrentView();
1318 else if (frames[i] instanceof TreePanel)
1320 target = ((TreePanel) frames[i]).getViewPort();
1322 else if (frames[i] instanceof PCAPanel)
1324 target = ((PCAPanel) frames[i]).av;
1326 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1328 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1331 if (source == target)
1337 frames[i].setClosed(true);
1341 frames[i].setIcon(minimize);
1344 frames[i].toFront();
1348 } catch (java.beans.PropertyVetoException ex)
1362 protected void preferences_actionPerformed(ActionEvent e)
1373 public void saveState_actionPerformed(ActionEvent e)
1375 JalviewFileChooser chooser = new JalviewFileChooser(
1376 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1377 { "jvp" }, new String[]
1378 { "Jalview Project" }, "Jalview Project");
1380 chooser.setFileView(new JalviewFileView());
1381 chooser.setDialogTitle("Save State");
1383 int value = chooser.showSaveDialog(this);
1385 if (value == JalviewFileChooser.APPROVE_OPTION)
1387 final Desktop me = this;
1388 final java.io.File choice = chooser.getSelectedFile();
1389 new Thread(new Runnable()
1394 setProgressBar("Saving jalview project " + choice.getName(),
1396 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1397 choice.getParent());
1398 // TODO catch and handle errors for savestate
1399 // TODO prevent user from messing with the Desktop whilst we're saving
1402 new Jalview2XML().SaveState(choice);
1403 } catch (OutOfMemoryError oom)
1405 new OOMWarning("Whilst saving current state to "
1406 + choice.getName(), oom);
1407 } catch (Exception ex)
1410 "Problems whilst trying to save to " + choice.getName(),
1412 JOptionPane.showMessageDialog(
1414 "Error whilst saving current state to "
1415 + choice.getName(), "Couldn't save project",
1416 JOptionPane.WARNING_MESSAGE);
1418 setProgressBar(null, choice.hashCode());
1430 public void loadState_actionPerformed(ActionEvent e)
1432 JalviewFileChooser chooser = new JalviewFileChooser(
1433 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1434 { "jvp","jar" }, new String[]
1435 { "Jalview Project", "Jalview Project (old)" }, "Jalview Project");
1436 chooser.setFileView(new JalviewFileView());
1437 chooser.setDialogTitle("Restore state");
1439 int value = chooser.showOpenDialog(this);
1441 if (value == JalviewFileChooser.APPROVE_OPTION)
1443 final String choice = chooser.getSelectedFile().getAbsolutePath();
1444 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1445 .getSelectedFile().getParent());
1446 new Thread(new Runnable()
1450 setProgressBar("loading jalview project " + choice,
1454 new Jalview2XML().LoadJalviewAlign(choice);
1455 } catch (OutOfMemoryError oom)
1457 new OOMWarning("Whilst loading project from " + choice, oom);
1458 } catch (Exception ex)
1460 Cache.log.error("Problems whilst loading project from "
1462 JOptionPane.showMessageDialog(Desktop.desktop,
1463 "Error whilst loading project from " + choice,
1464 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1466 setProgressBar(null, choice.hashCode());
1472 public void inputSequence_actionPerformed(ActionEvent e)
1474 new SequenceFetcher(this);
1477 JPanel progressPanel;
1479 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1481 public void startLoading(final String fileName)
1483 if (fileLoadingCount == 0)
1485 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1491 private JPanel addProgressPanel(String string)
1493 if (progressPanel == null)
1495 progressPanel = new JPanel(new GridLayout(1, 1));
1496 totalProgressCount = 0;
1497 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1499 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1500 JProgressBar progressBar = new JProgressBar();
1501 progressBar.setIndeterminate(true);
1503 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1505 thisprogress.add(progressBar, BorderLayout.CENTER);
1506 progressPanel.add(thisprogress);
1507 ((GridLayout) progressPanel.getLayout())
1508 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1509 ++totalProgressCount;
1510 instance.validate();
1511 return thisprogress;
1514 int totalProgressCount = 0;
1516 private void removeProgressPanel(JPanel progbar)
1518 if (progressPanel != null)
1520 synchronized(progressPanel) {
1521 progressPanel.remove(progbar);
1522 GridLayout gl = (GridLayout) progressPanel.getLayout();
1523 gl.setRows(gl.getRows() - 1);
1524 if (--totalProgressCount < 1)
1526 this.getContentPane().remove(progressPanel);
1527 progressPanel = null;
1534 public void stopLoading()
1537 if (fileLoadingCount < 1)
1539 while (fileLoadingPanels.size()>0)
1541 removeProgressPanel(fileLoadingPanels.remove(0));
1543 fileLoadingPanels.clear();
1544 fileLoadingCount = 0;
1549 public static int getViewCount(String alignmentId)
1551 AlignViewport[] aps = getViewports(alignmentId);
1552 return (aps == null) ? 0 : aps.length;
1557 * @param alignmentId
1558 * @return all AlignmentPanels concerning the alignmentId sequence set
1560 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1563 if (Desktop.desktop == null)
1565 // no frames created and in headless mode
1566 // TODO: verify that frames are recoverable when in headless mode
1569 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1570 ArrayList aps = new ArrayList();
1571 for (int t = 0; t < frames.length; t++)
1573 if (frames[t] instanceof AlignFrame)
1575 AlignFrame af = (AlignFrame) frames[t];
1576 for (int a = 0; a < af.alignPanels.size(); a++)
1578 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1579 .elementAt(a)).av.getSequenceSetId()))
1581 aps.add(af.alignPanels.elementAt(a));
1586 if (aps.size() == 0)
1590 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1591 for (int t = 0; t < vap.length; t++)
1593 vap[t] = (AlignmentPanel) aps.get(t);
1599 * get all the viewports on an alignment.
1601 * @param sequenceSetId
1602 * unique alignment id
1603 * @return all viewports on the alignment bound to sequenceSetId
1605 public static AlignViewport[] getViewports(String sequenceSetId)
1607 Vector viewp = new Vector();
1608 if (desktop != null)
1610 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1612 for (int t = 0; t < frames.length; t++)
1614 if (frames[t] instanceof AlignFrame)
1616 AlignFrame afr = ((AlignFrame) frames[t]);
1617 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1619 if (afr.alignPanels != null)
1621 for (int a = 0; a < afr.alignPanels.size(); a++)
1623 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1624 .elementAt(a)).av.getSequenceSetId()))
1626 viewp.addElement(((AlignmentPanel) afr.alignPanels
1633 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1638 if (viewp.size() > 0)
1640 AlignViewport[] vp = new AlignViewport[viewp.size()];
1648 public void explodeViews(AlignFrame af)
1650 int size = af.alignPanels.size();
1656 for (int i = 0; i < size; i++)
1658 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1659 AlignFrame newaf = new AlignFrame(ap);
1660 if (ap.av.explodedPosition != null
1661 && !ap.av.explodedPosition.equals(af.getBounds()))
1663 newaf.setBounds(ap.av.explodedPosition);
1666 ap.av.gatherViewsHere = false;
1668 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1669 AlignFrame.DEFAULT_HEIGHT);
1672 af.alignPanels.clear();
1673 af.closeMenuItem_actionPerformed(true);
1677 public void gatherViews(AlignFrame source)
1679 source.viewport.gatherViewsHere = true;
1680 source.viewport.explodedPosition = source.getBounds();
1681 JInternalFrame[] frames = desktop.getAllFrames();
1682 String viewId = source.viewport.getSequenceSetId();
1684 for (int t = 0; t < frames.length; t++)
1686 if (frames[t] instanceof AlignFrame && frames[t] != source)
1688 AlignFrame af = (AlignFrame) frames[t];
1689 boolean gatherThis = false;
1690 for (int a = 0; a < af.alignPanels.size(); a++)
1692 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1693 if (viewId.equals(ap.av.getSequenceSetId()))
1696 ap.av.gatherViewsHere = false;
1697 ap.av.explodedPosition = af.getBounds();
1698 source.addAlignmentPanel(ap, false);
1704 af.alignPanels.clear();
1705 af.closeMenuItem_actionPerformed(true);
1712 jalview.gui.VamsasApplication v_client = null;
1714 public void vamsasImport_actionPerformed(ActionEvent e)
1716 if (v_client == null)
1718 // Load and try to start a session.
1719 JalviewFileChooser chooser = new JalviewFileChooser(
1720 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1722 chooser.setFileView(new JalviewFileView());
1723 chooser.setDialogTitle("Open a saved VAMSAS session");
1724 chooser.setToolTipText(MessageManager.getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1726 int value = chooser.showOpenDialog(this);
1728 if (value == JalviewFileChooser.APPROVE_OPTION)
1730 String fle = chooser.getSelectedFile().toString();
1731 if (!vamsasImport(chooser.getSelectedFile()))
1733 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1734 MessageManager.formatMessage("label.couldnt_import_as_vamsas_session", new String[]{fle}),
1735 MessageManager.getString("label.vamsas_document_import_failed"),
1736 JOptionPane.ERROR_MESSAGE);
1742 jalview.bin.Cache.log
1743 .error("Implementation error - load session from a running session is not supported.");
1748 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1751 * @return true if import was a success and a session was started.
1753 public boolean vamsasImport(URL url)
1755 // TODO: create progress bar
1756 if (v_client != null)
1759 jalview.bin.Cache.log
1760 .error("Implementation error - load session from a running session is not supported.");
1766 // copy the URL content to a temporary local file
1767 // TODO: be a bit cleverer here with nio (?!)
1768 File file = File.createTempFile("vdocfromurl", ".vdj");
1769 FileOutputStream fos = new FileOutputStream(file);
1770 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1771 byte[] buffer = new byte[2048];
1773 while ((ln = bis.read(buffer)) > -1)
1775 fos.write(buffer, 0, ln);
1779 v_client = new jalview.gui.VamsasApplication(this, file,
1780 url.toExternalForm());
1781 } catch (Exception ex)
1783 jalview.bin.Cache.log.error(
1784 "Failed to create new vamsas session from contents of URL "
1788 setupVamsasConnectedGui();
1789 v_client.initial_update(); // TODO: thread ?
1790 return v_client.inSession();
1794 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1797 * @return true if import was a success and a session was started.
1799 public boolean vamsasImport(File file)
1801 if (v_client != null)
1804 jalview.bin.Cache.log
1805 .error("Implementation error - load session from a running session is not supported.");
1809 setProgressBar("Importing VAMSAS session from " + file.getName(),
1813 v_client = new jalview.gui.VamsasApplication(this, file, null);
1814 } catch (Exception ex)
1816 setProgressBar("Importing VAMSAS session from " + file.getName(),
1818 jalview.bin.Cache.log.error(
1819 "New vamsas session from existing session file failed:", ex);
1822 setupVamsasConnectedGui();
1823 v_client.initial_update(); // TODO: thread ?
1824 setProgressBar("Importing VAMSAS session from " + file.getName(),
1826 return v_client.inSession();
1829 public boolean joinVamsasSession(String mysesid)
1831 if (v_client != null)
1834 "Trying to join a vamsas session when another is already connected.");
1836 if (mysesid == null)
1838 throw new Error("Invalid vamsas session id.");
1840 v_client = new VamsasApplication(this, mysesid);
1841 setupVamsasConnectedGui();
1842 v_client.initial_update();
1843 return (v_client.inSession());
1846 public void vamsasStart_actionPerformed(ActionEvent e)
1848 if (v_client == null)
1851 // we just start a default session for moment.
1853 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1854 * getProperty("LAST_DIRECTORY"));
1856 * chooser.setFileView(new JalviewFileView());
1857 * chooser.setDialogTitle("Load Vamsas file");
1858 * chooser.setToolTipText("Import");
1860 * int value = chooser.showOpenDialog(this);
1862 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1863 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1865 v_client = new VamsasApplication(this);
1866 setupVamsasConnectedGui();
1867 v_client.initial_update(); // TODO: thread ?
1871 // store current data in session.
1872 v_client.push_update(); // TODO: thread
1876 protected void setupVamsasConnectedGui()
1878 vamsasStart.setText(MessageManager.getString("label.session_update"));
1879 vamsasSave.setVisible(true);
1880 vamsasStop.setVisible(true);
1881 vamsasImport.setVisible(false); // Document import to existing session is
1882 // not possible for vamsas-client-1.0.
1885 protected void setupVamsasDisconnectedGui()
1887 vamsasSave.setVisible(false);
1888 vamsasStop.setVisible(false);
1889 vamsasImport.setVisible(true);
1890 vamsasStart.setText(MessageManager.getString("label.new_vamsas_session"));
1893 public void vamsasStop_actionPerformed(ActionEvent e)
1895 if (v_client != null)
1897 v_client.end_session();
1899 setupVamsasDisconnectedGui();
1903 protected void buildVamsasStMenu()
1905 if (v_client == null)
1907 String[] sess = null;
1910 sess = VamsasApplication.getSessionList();
1911 } catch (Exception e)
1913 jalview.bin.Cache.log.warn(
1914 "Problem getting current sessions list.", e);
1919 jalview.bin.Cache.log.debug("Got current sessions list: "
1920 + sess.length + " entries.");
1921 VamsasStMenu.removeAll();
1922 for (int i = 0; i < sess.length; i++)
1924 JMenuItem sessit = new JMenuItem();
1925 sessit.setText(sess[i]);
1926 sessit.setToolTipText(MessageManager.formatMessage("label.connect_to_session", new String[]{sess[i]}));
1927 final Desktop dsktp = this;
1928 final String mysesid = sess[i];
1929 sessit.addActionListener(new ActionListener()
1932 public void actionPerformed(ActionEvent e)
1934 if (dsktp.v_client == null)
1936 Thread rthr = new Thread(new Runnable()
1941 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1942 dsktp.setupVamsasConnectedGui();
1943 dsktp.v_client.initial_update();
1951 VamsasStMenu.add(sessit);
1953 // don't show an empty menu.
1954 VamsasStMenu.setVisible(sess.length > 0);
1959 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1960 VamsasStMenu.removeAll();
1961 VamsasStMenu.setVisible(false);
1966 // Not interested in the content. Just hide ourselves.
1967 VamsasStMenu.setVisible(false);
1971 public void vamsasSave_actionPerformed(ActionEvent e)
1973 if (v_client != null)
1975 JalviewFileChooser chooser = new JalviewFileChooser(
1976 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1977 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1979 { "Vamsas Document" }, "Vamsas Document");
1981 chooser.setFileView(new JalviewFileView());
1982 chooser.setDialogTitle("Save Vamsas Document Archive");
1984 int value = chooser.showSaveDialog(this);
1986 if (value == JalviewFileChooser.APPROVE_OPTION)
1988 java.io.File choice = chooser.getSelectedFile();
1989 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1990 + choice.getName());
1991 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1992 String warnmsg = null;
1993 String warnttl = null;
1996 v_client.vclient.storeDocument(choice);
1999 warnttl = "Serious Problem saving Vamsas Document";
2000 warnmsg = ex.toString();
2001 jalview.bin.Cache.log.error("Error Whilst saving document to "
2004 } catch (Exception ex)
2006 warnttl = "Problem saving Vamsas Document.";
2007 warnmsg = ex.toString();
2008 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2012 removeProgressPanel(progpanel);
2013 if (warnmsg != null)
2015 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2017 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2023 JPanel vamUpdate = null;
2026 * hide vamsas user gui bits when a vamsas document event is being handled.
2029 * true to hide gui, false to reveal gui
2031 public void setVamsasUpdate(boolean b)
2033 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2034 + (b ? "in progress" : "finished"));
2036 if (vamUpdate != null)
2038 this.removeProgressPanel(vamUpdate);
2042 vamUpdate = this.addProgressPanel("Updating vamsas session");
2044 vamsasStart.setVisible(!b);
2045 vamsasStop.setVisible(!b);
2046 vamsasSave.setVisible(!b);
2049 public JInternalFrame[] getAllFrames()
2051 return desktop.getAllFrames();
2055 * Checks the given url to see if it gives a response indicating that the user
2056 * should be informed of a new questionnaire.
2060 public void checkForQuestionnaire(String url)
2062 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2063 // javax.swing.SwingUtilities.invokeLater(jvq);
2064 new Thread(jvq).start();
2068 * Proxy class for JDesktopPane which optionally displays the current memory
2069 * usage and highlights the desktop area with a red bar if free memory runs
2074 public class MyDesktopPane extends JDesktopPane implements Runnable
2077 boolean showMemoryUsage = false;
2081 java.text.NumberFormat df;
2083 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2086 public MyDesktopPane(boolean showMemoryUsage)
2088 showMemoryUsage(showMemoryUsage);
2091 public void showMemoryUsage(boolean showMemoryUsage)
2093 this.showMemoryUsage = showMemoryUsage;
2094 if (showMemoryUsage)
2096 Thread worker = new Thread(this);
2101 public boolean isShowMemoryUsage()
2103 return showMemoryUsage;
2108 df = java.text.NumberFormat.getNumberInstance();
2109 df.setMaximumFractionDigits(2);
2110 runtime = Runtime.getRuntime();
2112 while (showMemoryUsage)
2116 maxMemory = runtime.maxMemory() / 1048576f;
2117 allocatedMemory = runtime.totalMemory() / 1048576f;
2118 freeMemory = runtime.freeMemory() / 1048576f;
2119 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2121 percentUsage = (totalFreeMemory / maxMemory) * 100;
2123 // if (percentUsage < 20)
2125 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2127 // instance.set.setBorder(border1);
2130 // sleep after showing usage
2132 } catch (Exception ex)
2134 ex.printStackTrace();
2139 public void paintComponent(Graphics g)
2141 if (showMemoryUsage && g != null && df != null)
2143 if (percentUsage < 20)
2144 g.setColor(Color.red);
2145 FontMetrics fm = g.getFontMetrics();
2149 MessageManager.formatMessage("label.memory_stats", new String[]{df.format(totalFreeMemory),df.format(maxMemory),df.format(percentUsage)}), 10,
2150 getHeight() - fm.getHeight());
2157 * fixes stacking order after a modal dialog to ensure windows that should be
2158 * on top actually are
2160 public void relayerWindows()
2165 protected JMenuItem groovyShell;
2167 public void doGroovyCheck()
2169 if (jalview.bin.Cache.groovyJarsPresent())
2171 groovyShell = new JMenuItem();
2172 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2173 groovyShell.addActionListener(new ActionListener()
2175 public void actionPerformed(ActionEvent e)
2177 groovyShell_actionPerformed(e);
2180 toolsMenu.add(groovyShell);
2181 groovyShell.setVisible(true);
2186 * Accessor method to quickly get all the AlignmentFrames loaded.
2188 public static AlignFrame[] getAlignframes()
2190 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2196 Vector avp = new Vector();
2200 for (int i = frames.length - 1; i > -1; i--)
2202 if (frames[i] instanceof AlignFrame)
2204 AlignFrame af = (AlignFrame) frames[i];
2208 } catch (Exception ex)
2210 ex.printStackTrace();
2212 if (avp.size() == 0)
2216 AlignFrame afs[] = new AlignFrame[avp.size()];
2217 for (int i = 0, j = avp.size(); i < j; i++)
2219 afs[i] = (AlignFrame) avp.elementAt(i);
2225 public AppJmol[] getJmols()
2227 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2233 Vector avp = new Vector();
2237 for (int i = frames.length - 1; i > -1; i--)
2239 if (frames[i] instanceof AppJmol)
2241 AppJmol af = (AppJmol) frames[i];
2245 } catch (Exception ex)
2247 ex.printStackTrace();
2249 if (avp.size() == 0)
2253 AppJmol afs[] = new AppJmol[avp.size()];
2254 for (int i = 0, j = avp.size(); i < j; i++)
2256 afs[i] = (AppJmol) avp.elementAt(i);
2263 * Add Groovy Support to Jalview
2265 public void groovyShell_actionPerformed(ActionEvent e)
2267 // use reflection to avoid creating compilation dependency.
2268 if (!jalview.bin.Cache.groovyJarsPresent())
2271 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2275 Class gcClass = Desktop.class.getClassLoader().loadClass(
2276 "groovy.ui.Console");
2277 Constructor gccons = gcClass.getConstructor(null);
2278 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2280 { String.class, Object.class });
2281 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2282 Object gc = gccons.newInstance(null);
2283 setvar.invoke(gc, new Object[]
2284 { "Jalview", this });
2285 run.invoke(gc, null);
2286 } catch (Exception ex)
2288 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2290 .showInternalMessageDialog(
2293 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2294 "Jalview Groovy Support Failed",
2295 JOptionPane.ERROR_MESSAGE);
2300 * Progress bars managed by the IProgressIndicator method.
2302 private Hashtable<Long, JPanel> progressBars;
2304 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2309 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2311 public void setProgressBar(String message, long id)
2313 if (progressBars == null)
2315 progressBars = new Hashtable<Long, JPanel>();
2316 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2319 if (progressBars.get(new Long(id)) != null)
2321 JPanel progressPanel = progressBars.remove(new Long(id));
2322 if (progressBarHandlers.contains(new Long(id)))
2324 progressBarHandlers.remove(new Long(id));
2326 removeProgressPanel(progressPanel);
2330 progressBars.put(new Long(id), addProgressPanel(message));
2337 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2338 * jalview.gui.IProgressIndicatorHandler)
2340 public void registerHandler(final long id,
2341 final IProgressIndicatorHandler handler)
2343 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2346 "call setProgressBar before registering the progress bar's handler.");
2348 progressBarHandlers.put(new Long(id), handler);
2349 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2350 if (handler.canCancel())
2352 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
2353 final IProgressIndicator us = this;
2354 cancel.addActionListener(new ActionListener()
2357 public void actionPerformed(ActionEvent e)
2359 handler.cancelActivity(id);
2362 + ((JLabel) progressPanel.getComponent(0))
2366 progressPanel.add(cancel, BorderLayout.EAST);
2372 * @return true if any progress bars are still active
2375 public boolean operationInProgress()
2377 if (progressBars != null && progressBars.size() > 0)
2385 * This will return the first AlignFrame viewing AlignViewport av. It will
2386 * break if there are more than one AlignFrames viewing a particular av. This
2389 * @return alignFrame for av
2391 public static AlignFrame getAlignFrameFor(AlignViewport av)
2393 if (desktop != null)
2395 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2396 for (int panel = 0; aps != null && panel < aps.length; panel++)
2398 if (aps[panel] != null && aps[panel].av == av)
2400 return aps[panel].alignFrame;
2407 public VamsasApplication getVamsasApplication()
2414 * flag set if jalview GUI is being operated programmatically
2416 private boolean inBatchMode = false;
2419 * check if jalview GUI is being operated programmatically
2421 * @return inBatchMode
2423 public boolean isInBatchMode()
2429 * set flag if jalview GUI is being operated programmatically
2431 * @param inBatchMode
2433 public void setInBatchMode(boolean inBatchMode)
2435 this.inBatchMode = inBatchMode;
2438 public void startServiceDiscovery()
2440 startServiceDiscovery(false);
2443 public void startServiceDiscovery(boolean blocking)
2445 boolean alive = true;
2446 Thread t0 = null, t1 = null, t2 = null;
2447 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2450 // todo: changesupport handlers need to be transferred
2451 if (discoverer == null)
2453 discoverer = new jalview.ws.jws1.Discoverer();
2454 // register PCS handler for desktop.
2455 discoverer.addPropertyChangeListener(changeSupport);
2457 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2458 // until we phase out completely
2459 (t0 = new Thread(discoverer)).start();
2462 // ENFIN services are EOLed as of Jalview 2.8.1 release
2467 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2469 // EnfinEnvision web service menu entries are rebuild every time the
2470 // menu is shown, so no changeSupport events are needed.
2471 jalview.ws.EnfinEnvision2OneWay.getInstance();
2472 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2475 } catch (Exception e)
2478 .info("Exception when trying to launch Envision2 workflow discovery.",
2480 Cache.log.info(e.getStackTrace());
2484 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2486 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2488 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2490 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2496 // TODO: do rest service discovery
2505 } catch (Exception e)
2508 alive = (t1 != null && t1.isAlive())
2509 || (t2 != null && t2.isAlive())
2510 || (t3 != null && t3.isAlive())
2511 || (t0 != null && t0.isAlive());
2517 * called to check if the service discovery process completed successfully.
2521 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2523 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2525 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2526 .getErrorMessages();
2529 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2531 if (serviceChangedDialog == null)
2533 // only run if we aren't already displaying one of these.
2534 addDialogThread(serviceChangedDialog = new Runnable()
2540 * JalviewDialog jd =new JalviewDialog() {
2542 * @Override protected void cancelPressed() { // TODO
2543 * Auto-generated method stub
2545 * }@Override protected void okPressed() { // TODO
2546 * Auto-generated method stub
2548 * }@Override protected void raiseClosed() { // TODO
2549 * Auto-generated method stub
2551 * } }; jd.initDialogFrame(new
2552 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2553 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2554 * + " or mis-configured HTTP proxy settings.<br/>" +
2555 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2557 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2558 * ), true, true, "Web Service Configuration Problem", 450,
2561 * jd.waitForInput();
2567 "<html><table width=\"450\"><tr><td>"
2569 + "</td></tr></table>"
2570 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2571 + " or mis-configured HTTP proxy settings.</p>"
2572 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2573 + " Tools->Preferences dialog box to change them.</p></html>"),
2574 "Web Service Configuration Problem",
2575 JOptionPane.DEFAULT_OPTION,
2576 JOptionPane.ERROR_MESSAGE);
2577 serviceChangedDialog = null;
2586 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2593 private Runnable serviceChangedDialog = null;
2596 * start a thread to open a URL in the configured browser. Pops up a warning
2597 * dialog to the user if there is an exception when calling out to the browser
2602 public static void showUrl(final String url)
2604 showUrl(url, Desktop.instance);
2608 * Like showUrl but allows progress handler to be specified
2612 * (null) or object implementing IProgressIndicator
2614 public static void showUrl(final String url,
2615 final IProgressIndicator progress)
2617 new Thread(new Runnable()
2623 if (progress != null)
2625 progress.setProgressBar("Opening " + url, this.hashCode());
2627 jalview.util.BrowserLauncher.openURL(url);
2628 } catch (Exception ex)
2631 .showInternalMessageDialog(
2633 "Unixers: Couldn't find default web browser."
2634 + "\nAdd the full path to your browser in Preferences.",
2635 "Web browser not found",
2636 JOptionPane.WARNING_MESSAGE);
2638 ex.printStackTrace();
2640 if (progress != null)
2642 progress.setProgressBar(null, this.hashCode());
2648 public static WsParamSetManager wsparamManager = null;
2650 public static ParamManager getUserParameterStore()
2652 if (wsparamManager == null)
2654 wsparamManager = new WsParamSetManager();
2656 return wsparamManager;
2660 * static hyperlink handler proxy method for use by Jalview's internal windows
2664 public static void hyperlinkUpdate(HyperlinkEvent e)
2666 if (e.getEventType() == EventType.ACTIVATED)
2671 url = e.getURL().toString();
2672 Desktop.showUrl(url);
2673 } catch (Exception x)
2677 if (Cache.log != null)
2679 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2683 System.err.println("Couldn't handle string " + url
2687 // ignore any exceptions due to dud links.
2694 * single thread that handles display of dialogs to user.
2696 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2699 * flag indicating if dialogExecutor should try to acquire a permit
2701 private volatile boolean dialogPause = true;
2706 private java.util.concurrent.Semaphore block = new Semaphore(0);
2709 * add another dialog thread to the queue
2713 public void addDialogThread(final Runnable prompter)
2715 dialogExecutor.submit(new Runnable()
2724 } catch (InterruptedException x)
2729 if (instance == null)
2735 SwingUtilities.invokeAndWait(prompter);
2736 } catch (Exception q)
2738 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2744 public void startDialogQueue()
2746 // set the flag so we don't pause waiting for another permit and semaphore
2747 // the current task to begin
2748 dialogPause = false;