2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 import jalview.bin.Cache;
22 import jalview.io.FileLoader;
23 import jalview.io.FormatAdapter;
24 import jalview.io.IdentifyFile;
25 import jalview.io.JalviewFileChooser;
26 import jalview.io.JalviewFileView;
27 import jalview.util.MessageManager;
28 import jalview.ws.params.ParamManager;
30 import java.awt.BorderLayout;
31 import java.awt.Color;
32 import java.awt.Dimension;
33 import java.awt.FontMetrics;
34 import java.awt.Graphics;
35 import java.awt.GridLayout;
36 import java.awt.Point;
37 import java.awt.Rectangle;
38 import java.awt.Toolkit;
39 import java.awt.datatransfer.Clipboard;
40 import java.awt.datatransfer.ClipboardOwner;
41 import java.awt.datatransfer.DataFlavor;
42 import java.awt.datatransfer.Transferable;
43 import java.awt.dnd.DnDConstants;
44 import java.awt.dnd.DropTargetDragEvent;
45 import java.awt.dnd.DropTargetDropEvent;
46 import java.awt.dnd.DropTargetEvent;
47 import java.awt.dnd.DropTargetListener;
48 import java.awt.event.ActionEvent;
49 import java.awt.event.ActionListener;
50 import java.awt.event.FocusEvent;
51 import java.awt.event.FocusListener;
52 import java.awt.event.MouseAdapter;
53 import java.awt.event.MouseEvent;
54 import java.awt.event.MouseListener;
55 import java.awt.event.WindowAdapter;
56 import java.awt.event.WindowEvent;
57 import java.beans.PropertyChangeEvent;
58 import java.beans.PropertyChangeListener;
59 import java.beans.PropertyVetoException;
60 import java.io.BufferedInputStream;
62 import java.io.FileOutputStream;
63 import java.lang.reflect.Constructor;
65 import java.util.ArrayList;
66 import java.util.Hashtable;
67 import java.util.StringTokenizer;
68 import java.util.Vector;
69 import java.util.concurrent.ExecutorService;
70 import java.util.concurrent.Executors;
71 import java.util.concurrent.Semaphore;
73 import javax.swing.DefaultDesktopManager;
74 import javax.swing.DesktopManager;
75 import javax.swing.JButton;
76 import javax.swing.JComboBox;
77 import javax.swing.JComponent;
78 import javax.swing.JDesktopPane;
79 import javax.swing.JFrame;
80 import javax.swing.JInternalFrame;
81 import javax.swing.JLabel;
82 import javax.swing.JMenuItem;
83 import javax.swing.JOptionPane;
84 import javax.swing.JPanel;
85 import javax.swing.JPopupMenu;
86 import javax.swing.JProgressBar;
87 import javax.swing.SwingUtilities;
88 import javax.swing.event.HyperlinkEvent;
89 import javax.swing.event.MenuEvent;
90 import javax.swing.event.MenuListener;
91 import javax.swing.event.HyperlinkEvent.EventType;
98 * @version $Revision: 1.155 $
100 public class Desktop extends jalview.jbgui.GDesktop implements
101 DropTargetListener, ClipboardOwner, IProgressIndicator,
102 jalview.api.StructureSelectionManagerProvider
105 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
108 * news reader - null if it was never started.
110 private BlogReader jvnews = null;
114 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
116 public void addJalviewPropertyChangeListener(
117 PropertyChangeListener listener)
119 changeSupport.addJalviewPropertyChangeListener(listener);
123 * @param propertyName
125 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
126 * java.beans.PropertyChangeListener)
128 public void addJalviewPropertyChangeListener(String propertyName,
129 PropertyChangeListener listener)
131 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
135 * @param propertyName
137 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
138 * java.beans.PropertyChangeListener)
140 public void removeJalviewPropertyChangeListener(String propertyName,
141 PropertyChangeListener listener)
143 changeSupport.removeJalviewPropertyChangeListener(propertyName,
147 /** Singleton Desktop instance */
148 public static Desktop instance;
150 public static MyDesktopPane desktop;
152 static int openFrameCount = 0;
154 static final int xOffset = 30;
156 static final int yOffset = 30;
158 public static jalview.ws.jws1.Discoverer discoverer;
160 public static Object[] jalviewClipboard;
162 public static boolean internalCopy = false;
164 static int fileLoadingCount = 0;
166 class MyDesktopManager implements DesktopManager
169 private DesktopManager delegate;
171 public MyDesktopManager(DesktopManager delegate)
173 this.delegate = delegate;
176 public void activateFrame(JInternalFrame f)
180 delegate.activateFrame(f);
181 } catch (NullPointerException npe)
183 Point p = getMousePosition();
184 instance.showPasteMenu(p.x, p.y);
188 public void beginDraggingFrame(JComponent f)
190 delegate.beginDraggingFrame(f);
193 public void beginResizingFrame(JComponent f, int direction)
195 delegate.beginResizingFrame(f, direction);
198 public void closeFrame(JInternalFrame f)
200 delegate.closeFrame(f);
203 public void deactivateFrame(JInternalFrame f)
205 delegate.deactivateFrame(f);
208 public void deiconifyFrame(JInternalFrame f)
210 delegate.deiconifyFrame(f);
213 public void dragFrame(JComponent f, int newX, int newY)
219 delegate.dragFrame(f, newX, newY);
222 public void endDraggingFrame(JComponent f)
224 delegate.endDraggingFrame(f);
227 public void endResizingFrame(JComponent f)
229 delegate.endResizingFrame(f);
232 public void iconifyFrame(JInternalFrame f)
234 delegate.iconifyFrame(f);
237 public void maximizeFrame(JInternalFrame f)
239 delegate.maximizeFrame(f);
242 public void minimizeFrame(JInternalFrame f)
244 delegate.minimizeFrame(f);
247 public void openFrame(JInternalFrame f)
249 delegate.openFrame(f);
252 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
255 Rectangle b = desktop.getBounds();
260 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
263 public void setBoundsForFrame(JComponent f, int newX, int newY,
264 int newWidth, int newHeight)
266 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
269 // All other methods, simply delegate
274 * Creates a new Desktop object.
279 * A note to implementors. It is ESSENTIAL that any activities that might
280 * block are spawned off as threads rather than waited for during this
284 doVamsasClientCheck();
287 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
288 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
289 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
291 boolean showjconsole = jalview.bin.Cache.getDefault(
292 "SHOW_JAVA_CONSOLE", false);
293 desktop = new MyDesktopPane(selmemusage);
294 showMemusage.setSelected(selmemusage);
295 desktop.setBackground(Color.white);
296 getContentPane().setLayout(new BorderLayout());
297 // alternate config - have scrollbars - see notes in JAL-153
298 // JScrollPane sp = new JScrollPane();
299 // sp.getViewport().setView(desktop);
300 // getContentPane().add(sp, BorderLayout.CENTER);
301 getContentPane().add(desktop, BorderLayout.CENTER);
302 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
304 // This line prevents Windows Look&Feel resizing all new windows to maximum
305 // if previous window was maximised
306 desktop.setDesktopManager(new MyDesktopManager(
307 new DefaultDesktopManager()));
309 Rectangle dims = getLastKnownDimensions("");
316 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
317 setBounds((int) (screenSize.width - 900) / 2,
318 (int) (screenSize.height - 650) / 2, 900, 650);
320 jconsole = new Console(this, showjconsole);
321 // add essential build information
322 jconsole.setHeader("Jalview Desktop "
323 + jalview.bin.Cache.getProperty("VERSION") + "\n"
325 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
326 + "Java version: " + System.getProperty("java.version") + "\n"
327 + System.getProperty("os.arch") + " "
328 + System.getProperty("os.name") + " "
329 + System.getProperty("os.version"));
331 showConsole(showjconsole);
333 showNews.setVisible(false);
335 this.addWindowListener(new WindowAdapter()
337 public void windowClosing(WindowEvent evt)
344 this.addMouseListener(ma = new MouseAdapter()
346 public void mousePressed(MouseEvent evt)
348 if (SwingUtilities.isRightMouseButton(evt))
350 showPasteMenu(evt.getX(), evt.getY());
354 desktop.addMouseListener(ma);
356 this.addFocusListener(new FocusListener()
360 public void focusLost(FocusEvent e)
362 // TODO Auto-generated method stub
367 public void focusGained(FocusEvent e)
369 Cache.log.debug("Relaying windows after focus gain");
370 // make sure that we sort windows properly after we gain focus
371 instance.relayerWindows();
374 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
375 // Spawn a thread that shows the splashscreen
376 SwingUtilities.invokeLater(new Runnable()
385 // Thread off a new instance of the file chooser - this reduces the time it
386 // takes to open it later on.
387 new Thread(new Runnable()
391 Cache.log.debug("Filechooser init thread started.");
392 JalviewFileChooser chooser = new JalviewFileChooser(
393 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
394 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
395 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
396 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
397 Cache.log.debug("Filechooser init thread finished.");
400 // Add the service change listener
401 changeSupport.addJalviewPropertyChangeListener("services",
402 new PropertyChangeListener()
406 public void propertyChange(PropertyChangeEvent evt)
408 Cache.log.debug("Firing service changed event for "
409 + evt.getNewValue());
410 JalviewServicesChanged(evt);
416 public void checkForNews()
418 final Desktop me = this;
419 // Thread off the news reader, in case there are connection problems.
420 addDialogThread(new Runnable()
425 Cache.log.debug("Starting news thread.");
427 jvnews = new BlogReader(me);
428 showNews.setVisible(true);
429 Cache.log.debug("Completed news thread.");
434 protected void showNews_actionPerformed(ActionEvent e)
436 showNews(showNews.isSelected());
439 void showNews(boolean visible)
442 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
443 showNews.setSelected(visible);
444 if (visible && !jvnews.isVisible())
446 new Thread(new Runnable()
451 long instance = System.currentTimeMillis();
452 Desktop.instance.setProgressBar("Refreshing news", instance);
453 jvnews.refreshNews();
454 Desktop.instance.setProgressBar(null, instance);
463 * recover the last known dimensions for a jalview window
466 * - empty string is desktop, all other windows have unique prefix
467 * @return null or last known dimensions scaled to current geometry (if last
468 * window geom was known)
470 Rectangle getLastKnownDimensions(String windowName)
472 // TODO: lock aspect ratio for scaling desktop Bug #0058199
473 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
474 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
475 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
476 String width = jalview.bin.Cache.getProperty(windowName
478 String height = jalview.bin.Cache.getProperty(windowName
480 if ((x != null) && (y != null) && (width != null) && (height != null))
482 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
483 .parseInt(width), ih = Integer.parseInt(height);
484 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
486 // attempt #1 - try to cope with change in screen geometry - this
487 // version doesn't preserve original jv aspect ratio.
488 // take ratio of current screen size vs original screen size.
489 double sw = ((1f * screenSize.width) / (1f * Integer
490 .parseInt(jalview.bin.Cache
491 .getProperty("SCREENGEOMETRY_WIDTH"))));
492 double sh = ((1f * screenSize.height) / (1f * Integer
493 .parseInt(jalview.bin.Cache
494 .getProperty("SCREENGEOMETRY_HEIGHT"))));
495 // rescale the bounds depending upon the current screen geometry.
496 ix = (int) (ix * sw);
497 iw = (int) (iw * sw);
498 iy = (int) (iy * sh);
499 ih = (int) (ih * sh);
500 while (ix >= screenSize.width)
502 jalview.bin.Cache.log
503 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
504 ix -= screenSize.width;
506 while (iy >= screenSize.height)
508 jalview.bin.Cache.log
509 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
510 iy -= screenSize.height;
512 jalview.bin.Cache.log.debug("Got last known dimensions for "
513 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
516 // return dimensions for new instance
517 return new Rectangle(ix, iy, iw, ih);
522 private void doVamsasClientCheck()
524 if (jalview.bin.Cache.vamsasJarsPresent())
526 setupVamsasDisconnectedGui();
527 VamsasMenu.setVisible(true);
528 final Desktop us = this;
529 VamsasMenu.addMenuListener(new MenuListener()
531 // this listener remembers when the menu was first selected, and
532 // doesn't rebuild the session list until it has been cleared and
534 boolean refresh = true;
536 public void menuCanceled(MenuEvent e)
541 public void menuDeselected(MenuEvent e)
546 public void menuSelected(MenuEvent e)
550 us.buildVamsasStMenu();
555 vamsasStart.setVisible(true);
559 void showPasteMenu(int x, int y)
561 JPopupMenu popup = new JPopupMenu();
562 JMenuItem item = new JMenuItem(MessageManager.getString("label.paste_new_window"));
563 item.addActionListener(new ActionListener()
565 public void actionPerformed(ActionEvent evt)
572 popup.show(this, x, y);
579 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
580 Transferable contents = c.getContents(this);
582 if (contents != null)
584 String file = (String) contents
585 .getTransferData(DataFlavor.stringFlavor);
587 String format = new IdentifyFile().Identify(file,
588 FormatAdapter.PASTE);
590 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
593 } catch (Exception ex)
596 .println("Unable to paste alignment from system clipboard:\n"
602 * Adds and opens the given frame to the desktop
613 public static synchronized void addInternalFrame(
614 final JInternalFrame frame, String title, int w, int h)
616 addInternalFrame(frame, title, w, h, true);
633 public static synchronized void addInternalFrame(
634 final JInternalFrame frame, String title, int w, int h,
638 // TODO: allow callers to determine X and Y position of frame (eg. via
640 // TODO: consider fixing method to update entries in the window submenu with
641 // the current window title
643 frame.setTitle(title);
644 if (frame.getWidth() < 1 || frame.getHeight() < 1)
648 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
649 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
650 // IF JALVIEW IS RUNNING HEADLESS
651 // ///////////////////////////////////////////////
652 if (instance == null || (System.getProperty("java.awt.headless") != null
653 && System.getProperty("java.awt.headless").equals("true")))
660 frame.setVisible(true);
661 frame.setClosable(true);
662 frame.setResizable(resizable);
663 frame.setMaximizable(resizable);
664 frame.setIconifiable(resizable);
665 frame.setFrameIcon(null);
667 if (frame.getX() < 1 && frame.getY() < 1)
669 frame.setLocation(xOffset * openFrameCount, yOffset
670 * ((openFrameCount - 1) % 10) + yOffset);
673 final JMenuItem menuItem = new JMenuItem(title);
674 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
676 public void internalFrameActivated(
677 javax.swing.event.InternalFrameEvent evt)
679 JInternalFrame itf = desktop.getSelectedFrame();
687 public void internalFrameClosed(
688 javax.swing.event.InternalFrameEvent evt)
690 PaintRefresher.RemoveComponent(frame);
692 windowMenu.remove(menuItem);
693 JInternalFrame itf = desktop.getSelectedFrame();
702 menuItem.addActionListener(new ActionListener()
704 public void actionPerformed(ActionEvent e)
708 frame.setSelected(true);
709 frame.setIcon(false);
710 } catch (java.beans.PropertyVetoException ex)
716 menuItem.addMouseListener(new MouseListener()
720 public void mouseReleased(MouseEvent e)
725 public void mousePressed(MouseEvent e)
730 public void mouseExited(MouseEvent e)
734 frame.setSelected(false);
735 } catch (PropertyVetoException e1)
741 public void mouseEntered(MouseEvent e)
745 frame.setSelected(true);
746 } catch (PropertyVetoException e1)
752 public void mouseClicked(MouseEvent e)
758 windowMenu.add(menuItem);
764 frame.setSelected(true);
765 frame.requestFocus();
766 } catch (java.beans.PropertyVetoException ve)
768 } catch (java.lang.ClassCastException cex)
771 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
776 public void lostOwnership(Clipboard clipboard, Transferable contents)
780 Desktop.jalviewClipboard = null;
783 internalCopy = false;
786 public void dragEnter(DropTargetDragEvent evt)
790 public void dragExit(DropTargetEvent evt)
794 public void dragOver(DropTargetDragEvent evt)
798 public void dropActionChanged(DropTargetDragEvent evt)
808 public void drop(DropTargetDropEvent evt)
810 boolean success=true;
811 Transferable t = evt.getTransferable();
812 java.util.List files = null;
813 java.util.List protocols = null;
817 DataFlavor uriListFlavor = new DataFlavor(
818 "text/uri-list;class=java.lang.String");
819 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
821 // Works on Windows and MacOSX
822 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
823 files = (java.util.List) t
824 .getTransferData(DataFlavor.javaFileListFlavor);
826 else if (t.isDataFlavorSupported(uriListFlavor))
828 // This is used by Unix drag system
829 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
830 String data = (String) t.getTransferData(uriListFlavor);
831 files = new java.util.ArrayList(1);
832 protocols = new java.util.ArrayList(1);
833 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
834 data, "\r\n"); st.hasMoreTokens();)
836 String s = st.nextToken();
837 if (s.startsWith("#"))
839 // the line is a comment (as per the RFC 2483)
842 java.net.URI uri = new java.net.URI(s);
843 if (uri.getScheme().toLowerCase().startsWith("http"))
845 protocols.add(FormatAdapter.URL);
846 files.add(uri.toString());
850 // otherwise preserve old behaviour: catch all for file objects
851 java.io.File file = new java.io.File(uri);
852 protocols.add(FormatAdapter.FILE);
853 files.add(file.toString());
857 } catch (Exception e)
866 for (int i = 0; i < files.size(); i++)
868 String file = files.get(i).toString();
869 String protocol = (protocols == null) ? FormatAdapter.FILE
870 : (String) protocols.get(i);
871 String format = null;
873 if (file.endsWith(".jar"))
880 format = new IdentifyFile().Identify(file, protocol);
883 new FileLoader().LoadFile(file, protocol, format);
886 } catch (Exception ex)
891 evt.dropComplete(success); // need this to ensure input focus is properly transfered to any new windows created
900 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
902 JalviewFileChooser chooser = new JalviewFileChooser(
903 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
904 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
905 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
906 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
908 chooser.setFileView(new JalviewFileView());
909 chooser.setDialogTitle(MessageManager.getString("label.open_local_file"));
910 chooser.setToolTipText(MessageManager.getString("action.open"));
912 int value = chooser.showOpenDialog(this);
914 if (value == JalviewFileChooser.APPROVE_OPTION)
916 String choice = chooser.getSelectedFile().getPath();
917 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
918 .getSelectedFile().getParent());
920 String format = null;
921 if (chooser.getSelectedFormat()!=null && chooser.getSelectedFormat().equals("Jalview"))
927 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
930 if (viewport != null)
932 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
937 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
948 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
950 // This construct allows us to have a wider textfield
952 JLabel label = new JLabel(MessageManager.getString("label.input_file_url"));
953 final JComboBox history = new JComboBox();
955 JPanel panel = new JPanel(new GridLayout(2, 1));
958 history.setPreferredSize(new Dimension(400, 20));
959 history.setEditable(true);
960 history.addItem("http://www.");
962 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
966 if (historyItems != null)
968 st = new StringTokenizer(historyItems, "\t");
970 while (st.hasMoreTokens())
972 history.addItem(st.nextElement());
976 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
977 MessageManager.getString("label.input_alignment_from_url"), JOptionPane.OK_CANCEL_OPTION);
979 if (reply != JOptionPane.OK_OPTION)
984 String url = history.getSelectedItem().toString();
986 if (url.toLowerCase().endsWith(".jar"))
988 if (viewport != null)
990 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
995 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1000 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1002 if (format.equals("URL NOT FOUND"))
1004 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1005 "Couldn't locate " + url, "URL not found",
1006 JOptionPane.WARNING_MESSAGE);
1011 if (viewport != null)
1013 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1017 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1028 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1030 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1031 cap.setForInput(viewport);
1032 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1040 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1042 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1043 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1045 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1046 getBounds().y, getWidth(), getHeight()));
1048 if (jconsole != null)
1050 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1051 jconsole.stopConsole();
1055 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1058 if (dialogExecutor != null)
1060 dialogExecutor.shutdownNow();
1066 private void storeLastKnownDimensions(String string, Rectangle jc)
1068 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1069 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1070 + " height:" + jc.height);
1072 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1073 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1074 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1075 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1084 public void aboutMenuItem_actionPerformed(ActionEvent e)
1086 // StringBuffer message = getAboutMessage(false);
1087 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1089 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1090 new Thread(new Runnable()
1094 new SplashScreen(true);
1099 public StringBuffer getAboutMessage(boolean shortv)
1101 StringBuffer message = new StringBuffer();
1102 message.append("<html>");
1105 message.append("<h1><strong>Version: "
1106 + jalview.bin.Cache.getProperty("VERSION")
1107 + "</strong></h1><br>");
1108 message.append("<strong>Last Updated: <em>"
1109 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1110 + "</em></strong>");
1116 message.append("<strong>Version "
1117 + jalview.bin.Cache.getProperty("VERSION")
1118 + "; last updated: "
1119 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1122 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1125 message.append("<br>...Checking latest version...</br>");
1127 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1128 .equals(jalview.bin.Cache.getProperty("VERSION")))
1130 boolean red = false;
1131 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1132 .indexOf("automated build") == -1)
1135 // Displayed when code version and jnlp version do not match and code
1136 // version is not a development build
1137 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1140 message.append("<br>!! Version "
1141 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1143 + " is available for download from "
1144 + jalview.bin.Cache.getDefault("www.jalview.org",
1145 "http://www.jalview.org") + " !!");
1148 message.append("</div>");
1151 message.append("<br>Authors: "
1155 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1156 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1157 + "<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"
1158 + "<br>If you use Jalview, please cite:"
1159 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1160 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1161 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1172 public void documentationMenuItem_actionPerformed(ActionEvent e)
1176 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1177 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1178 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1180 javax.help.HelpBroker hb = hs.createHelpBroker();
1181 hb.setCurrentID("home");
1182 hb.setDisplayed(true);
1183 } catch (Exception ex)
1188 public void closeAll_actionPerformed(ActionEvent e)
1190 JInternalFrame[] frames = desktop.getAllFrames();
1191 for (int i = 0; i < frames.length; i++)
1195 frames[i].setClosed(true);
1196 } catch (java.beans.PropertyVetoException ex)
1200 System.out.println("ALL CLOSED");
1201 if (v_client != null)
1203 // TODO clear binding to vamsas document objects on close_all
1208 public void raiseRelated_actionPerformed(ActionEvent e)
1210 reorderAssociatedWindows(false, false);
1213 public void minimizeAssociated_actionPerformed(ActionEvent e)
1215 reorderAssociatedWindows(true, false);
1218 void closeAssociatedWindows()
1220 reorderAssociatedWindows(false, true);
1226 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1229 protected void garbageCollect_actionPerformed(ActionEvent e)
1231 // We simply collect the garbage
1232 jalview.bin.Cache.log.debug("Collecting garbage...");
1234 jalview.bin.Cache.log.debug("Finished garbage collection.");
1241 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1244 protected void showMemusage_actionPerformed(ActionEvent e)
1246 desktop.showMemoryUsage(showMemusage.isSelected());
1253 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1256 protected void showConsole_actionPerformed(ActionEvent e)
1258 showConsole(showConsole.isSelected());
1261 Console jconsole = null;
1264 * control whether the java console is visible or not
1268 void showConsole(boolean selected)
1270 showConsole.setSelected(selected);
1271 // TODO: decide if we should update properties file
1272 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1274 jconsole.setVisible(selected);
1277 void reorderAssociatedWindows(boolean minimize, boolean close)
1279 JInternalFrame[] frames = desktop.getAllFrames();
1280 if (frames == null || frames.length < 1)
1285 AlignViewport source = null, target = null;
1286 if (frames[0] instanceof AlignFrame)
1288 source = ((AlignFrame) frames[0]).getCurrentView();
1290 else if (frames[0] instanceof TreePanel)
1292 source = ((TreePanel) frames[0]).getViewPort();
1294 else if (frames[0] instanceof PCAPanel)
1296 source = ((PCAPanel) frames[0]).av;
1298 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1300 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1305 for (int i = 0; i < frames.length; i++)
1308 if (frames[i] == null)
1312 if (frames[i] instanceof AlignFrame)
1314 target = ((AlignFrame) frames[i]).getCurrentView();
1316 else if (frames[i] instanceof TreePanel)
1318 target = ((TreePanel) frames[i]).getViewPort();
1320 else if (frames[i] instanceof PCAPanel)
1322 target = ((PCAPanel) frames[i]).av;
1324 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1326 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1329 if (source == target)
1335 frames[i].setClosed(true);
1339 frames[i].setIcon(minimize);
1342 frames[i].toFront();
1346 } catch (java.beans.PropertyVetoException ex)
1360 protected void preferences_actionPerformed(ActionEvent e)
1371 public void saveState_actionPerformed(ActionEvent e)
1373 JalviewFileChooser chooser = new JalviewFileChooser(
1374 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1375 { "jar" }, new String[]
1376 { "Jalview Project" }, "Jalview Project");
1378 chooser.setFileView(new JalviewFileView());
1379 chooser.setDialogTitle("Save State");
1381 int value = chooser.showSaveDialog(this);
1383 if (value == JalviewFileChooser.APPROVE_OPTION)
1385 final Desktop me = this;
1386 final java.io.File choice = chooser.getSelectedFile();
1387 new Thread(new Runnable()
1392 setProgressBar("Saving jalview project " + choice.getName(),
1394 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1395 choice.getParent());
1396 // TODO catch and handle errors for savestate
1397 // TODO prevent user from messing with the Desktop whilst we're saving
1400 new Jalview2XML().SaveState(choice);
1401 } catch (OutOfMemoryError oom)
1403 new OOMWarning("Whilst saving current state to "
1404 + choice.getName(), oom);
1405 } catch (Exception ex)
1408 "Problems whilst trying to save to " + choice.getName(),
1410 JOptionPane.showMessageDialog(
1412 "Error whilst saving current state to "
1413 + choice.getName(), "Couldn't save project",
1414 JOptionPane.WARNING_MESSAGE);
1416 setProgressBar(null, choice.hashCode());
1428 public void loadState_actionPerformed(ActionEvent e)
1430 JalviewFileChooser chooser = new JalviewFileChooser(
1431 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1432 { "jar" }, new String[]
1433 { "Jalview Project" }, "Jalview Project");
1434 chooser.setFileView(new JalviewFileView());
1435 chooser.setDialogTitle("Restore state");
1437 int value = chooser.showOpenDialog(this);
1439 if (value == JalviewFileChooser.APPROVE_OPTION)
1441 final String choice = chooser.getSelectedFile().getAbsolutePath();
1442 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1443 .getSelectedFile().getParent());
1444 new Thread(new Runnable()
1448 setProgressBar("loading jalview project " + choice,
1452 new Jalview2XML().LoadJalviewAlign(choice);
1453 } catch (OutOfMemoryError oom)
1455 new OOMWarning("Whilst loading project from " + choice, oom);
1456 } catch (Exception ex)
1458 Cache.log.error("Problems whilst loading project from "
1460 JOptionPane.showMessageDialog(Desktop.desktop,
1461 "Error whilst loading project from " + choice,
1462 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1464 setProgressBar(null, choice.hashCode());
1470 public void inputSequence_actionPerformed(ActionEvent e)
1472 new SequenceFetcher(this);
1475 JPanel progressPanel;
1477 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1479 public void startLoading(final String fileName)
1481 if (fileLoadingCount == 0)
1483 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1489 private JPanel addProgressPanel(String string)
1491 if (progressPanel == null)
1493 progressPanel = new JPanel(new GridLayout(1, 1));
1494 totalProgressCount = 0;
1495 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1497 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1498 JProgressBar progressBar = new JProgressBar();
1499 progressBar.setIndeterminate(true);
1501 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1503 thisprogress.add(progressBar, BorderLayout.CENTER);
1504 progressPanel.add(thisprogress);
1505 ((GridLayout) progressPanel.getLayout())
1506 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1507 ++totalProgressCount;
1508 instance.validate();
1509 return thisprogress;
1512 int totalProgressCount = 0;
1514 private void removeProgressPanel(JPanel progbar)
1516 if (progressPanel != null)
1518 synchronized(progressPanel) {
1519 progressPanel.remove(progbar);
1520 GridLayout gl = (GridLayout) progressPanel.getLayout();
1521 gl.setRows(gl.getRows() - 1);
1522 if (--totalProgressCount < 1)
1524 this.getContentPane().remove(progressPanel);
1525 progressPanel = null;
1532 public void stopLoading()
1535 if (fileLoadingCount < 1)
1537 while (fileLoadingPanels.size()>0)
1539 removeProgressPanel(fileLoadingPanels.remove(0));
1541 fileLoadingPanels.clear();
1542 fileLoadingCount = 0;
1547 public static int getViewCount(String alignmentId)
1549 AlignViewport[] aps = getViewports(alignmentId);
1550 return (aps == null) ? 0 : aps.length;
1555 * @param alignmentId
1556 * @return all AlignmentPanels concerning the alignmentId sequence set
1558 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1561 if (Desktop.desktop == null)
1563 // no frames created and in headless mode
1564 // TODO: verify that frames are recoverable when in headless mode
1567 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1568 ArrayList aps = new ArrayList();
1569 for (int t = 0; t < frames.length; t++)
1571 if (frames[t] instanceof AlignFrame)
1573 AlignFrame af = (AlignFrame) frames[t];
1574 for (int a = 0; a < af.alignPanels.size(); a++)
1576 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1577 .elementAt(a)).av.getSequenceSetId()))
1579 aps.add(af.alignPanels.elementAt(a));
1584 if (aps.size() == 0)
1588 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1589 for (int t = 0; t < vap.length; t++)
1591 vap[t] = (AlignmentPanel) aps.get(t);
1597 * get all the viewports on an alignment.
1599 * @param sequenceSetId
1600 * unique alignment id
1601 * @return all viewports on the alignment bound to sequenceSetId
1603 public static AlignViewport[] getViewports(String sequenceSetId)
1605 Vector viewp = new Vector();
1606 if (desktop != null)
1608 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1610 for (int t = 0; t < frames.length; t++)
1612 if (frames[t] instanceof AlignFrame)
1614 AlignFrame afr = ((AlignFrame) frames[t]);
1615 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1617 if (afr.alignPanels != null)
1619 for (int a = 0; a < afr.alignPanels.size(); a++)
1621 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1622 .elementAt(a)).av.getSequenceSetId()))
1624 viewp.addElement(((AlignmentPanel) afr.alignPanels
1631 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1636 if (viewp.size() > 0)
1638 AlignViewport[] vp = new AlignViewport[viewp.size()];
1646 public void explodeViews(AlignFrame af)
1648 int size = af.alignPanels.size();
1654 for (int i = 0; i < size; i++)
1656 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1657 AlignFrame newaf = new AlignFrame(ap);
1658 if (ap.av.explodedPosition != null
1659 && !ap.av.explodedPosition.equals(af.getBounds()))
1661 newaf.setBounds(ap.av.explodedPosition);
1664 ap.av.gatherViewsHere = false;
1666 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1667 AlignFrame.DEFAULT_HEIGHT);
1670 af.alignPanels.clear();
1671 af.closeMenuItem_actionPerformed(true);
1675 public void gatherViews(AlignFrame source)
1677 source.viewport.gatherViewsHere = true;
1678 source.viewport.explodedPosition = source.getBounds();
1679 JInternalFrame[] frames = desktop.getAllFrames();
1680 String viewId = source.viewport.getSequenceSetId();
1682 for (int t = 0; t < frames.length; t++)
1684 if (frames[t] instanceof AlignFrame && frames[t] != source)
1686 AlignFrame af = (AlignFrame) frames[t];
1687 boolean gatherThis = false;
1688 for (int a = 0; a < af.alignPanels.size(); a++)
1690 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1691 if (viewId.equals(ap.av.getSequenceSetId()))
1694 ap.av.gatherViewsHere = false;
1695 ap.av.explodedPosition = af.getBounds();
1696 source.addAlignmentPanel(ap, false);
1702 af.alignPanels.clear();
1703 af.closeMenuItem_actionPerformed(true);
1710 jalview.gui.VamsasApplication v_client = null;
1712 public void vamsasImport_actionPerformed(ActionEvent e)
1714 if (v_client == null)
1716 // Load and try to start a session.
1717 JalviewFileChooser chooser = new JalviewFileChooser(
1718 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1720 chooser.setFileView(new JalviewFileView());
1721 chooser.setDialogTitle("Open a saved VAMSAS session");
1722 chooser.setToolTipText(MessageManager.getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1724 int value = chooser.showOpenDialog(this);
1726 if (value == JalviewFileChooser.APPROVE_OPTION)
1728 String fle = chooser.getSelectedFile().toString();
1729 if (!vamsasImport(chooser.getSelectedFile()))
1731 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1732 MessageManager.formatMessage("label.couldnt_import_as_vamsas_session", new String[]{fle}),
1733 MessageManager.getString("label.vamsas_document_import_failed"),
1734 JOptionPane.ERROR_MESSAGE);
1740 jalview.bin.Cache.log
1741 .error("Implementation error - load session from a running session is not supported.");
1746 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1749 * @return true if import was a success and a session was started.
1751 public boolean vamsasImport(URL url)
1753 // TODO: create progress bar
1754 if (v_client != null)
1757 jalview.bin.Cache.log
1758 .error("Implementation error - load session from a running session is not supported.");
1764 // copy the URL content to a temporary local file
1765 // TODO: be a bit cleverer here with nio (?!)
1766 File file = File.createTempFile("vdocfromurl", ".vdj");
1767 FileOutputStream fos = new FileOutputStream(file);
1768 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1769 byte[] buffer = new byte[2048];
1771 while ((ln = bis.read(buffer)) > -1)
1773 fos.write(buffer, 0, ln);
1777 v_client = new jalview.gui.VamsasApplication(this, file,
1778 url.toExternalForm());
1779 } catch (Exception ex)
1781 jalview.bin.Cache.log.error(
1782 "Failed to create new vamsas session from contents of URL "
1786 setupVamsasConnectedGui();
1787 v_client.initial_update(); // TODO: thread ?
1788 return v_client.inSession();
1792 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1795 * @return true if import was a success and a session was started.
1797 public boolean vamsasImport(File file)
1799 if (v_client != null)
1802 jalview.bin.Cache.log
1803 .error("Implementation error - load session from a running session is not supported.");
1807 setProgressBar("Importing VAMSAS session from " + file.getName(),
1811 v_client = new jalview.gui.VamsasApplication(this, file, null);
1812 } catch (Exception ex)
1814 setProgressBar("Importing VAMSAS session from " + file.getName(),
1816 jalview.bin.Cache.log.error(
1817 "New vamsas session from existing session file failed:", ex);
1820 setupVamsasConnectedGui();
1821 v_client.initial_update(); // TODO: thread ?
1822 setProgressBar("Importing VAMSAS session from " + file.getName(),
1824 return v_client.inSession();
1827 public boolean joinVamsasSession(String mysesid)
1829 if (v_client != null)
1832 "Trying to join a vamsas session when another is already connected.");
1834 if (mysesid == null)
1836 throw new Error("Invalid vamsas session id.");
1838 v_client = new VamsasApplication(this, mysesid);
1839 setupVamsasConnectedGui();
1840 v_client.initial_update();
1841 return (v_client.inSession());
1844 public void vamsasStart_actionPerformed(ActionEvent e)
1846 if (v_client == null)
1849 // we just start a default session for moment.
1851 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1852 * getProperty("LAST_DIRECTORY"));
1854 * chooser.setFileView(new JalviewFileView());
1855 * chooser.setDialogTitle("Load Vamsas file");
1856 * chooser.setToolTipText("Import");
1858 * int value = chooser.showOpenDialog(this);
1860 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1861 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1863 v_client = new VamsasApplication(this);
1864 setupVamsasConnectedGui();
1865 v_client.initial_update(); // TODO: thread ?
1869 // store current data in session.
1870 v_client.push_update(); // TODO: thread
1874 protected void setupVamsasConnectedGui()
1876 vamsasStart.setText(MessageManager.getString("label.session_update"));
1877 vamsasSave.setVisible(true);
1878 vamsasStop.setVisible(true);
1879 vamsasImport.setVisible(false); // Document import to existing session is
1880 // not possible for vamsas-client-1.0.
1883 protected void setupVamsasDisconnectedGui()
1885 vamsasSave.setVisible(false);
1886 vamsasStop.setVisible(false);
1887 vamsasImport.setVisible(true);
1888 vamsasStart.setText(MessageManager.getString("label.new_vamsas_session"));
1891 public void vamsasStop_actionPerformed(ActionEvent e)
1893 if (v_client != null)
1895 v_client.end_session();
1897 setupVamsasDisconnectedGui();
1901 protected void buildVamsasStMenu()
1903 if (v_client == null)
1905 String[] sess = null;
1908 sess = VamsasApplication.getSessionList();
1909 } catch (Exception e)
1911 jalview.bin.Cache.log.warn(
1912 "Problem getting current sessions list.", e);
1917 jalview.bin.Cache.log.debug("Got current sessions list: "
1918 + sess.length + " entries.");
1919 VamsasStMenu.removeAll();
1920 for (int i = 0; i < sess.length; i++)
1922 JMenuItem sessit = new JMenuItem();
1923 sessit.setText(sess[i]);
1924 sessit.setToolTipText(MessageManager.formatMessage("label.connect_to_session", new String[]{sess[i]}));
1925 final Desktop dsktp = this;
1926 final String mysesid = sess[i];
1927 sessit.addActionListener(new ActionListener()
1930 public void actionPerformed(ActionEvent e)
1932 if (dsktp.v_client == null)
1934 Thread rthr = new Thread(new Runnable()
1939 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1940 dsktp.setupVamsasConnectedGui();
1941 dsktp.v_client.initial_update();
1949 VamsasStMenu.add(sessit);
1951 // don't show an empty menu.
1952 VamsasStMenu.setVisible(sess.length > 0);
1957 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1958 VamsasStMenu.removeAll();
1959 VamsasStMenu.setVisible(false);
1964 // Not interested in the content. Just hide ourselves.
1965 VamsasStMenu.setVisible(false);
1969 public void vamsasSave_actionPerformed(ActionEvent e)
1971 if (v_client != null)
1973 JalviewFileChooser chooser = new JalviewFileChooser(
1974 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1975 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1977 { "Vamsas Document" }, "Vamsas Document");
1979 chooser.setFileView(new JalviewFileView());
1980 chooser.setDialogTitle("Save Vamsas Document Archive");
1982 int value = chooser.showSaveDialog(this);
1984 if (value == JalviewFileChooser.APPROVE_OPTION)
1986 java.io.File choice = chooser.getSelectedFile();
1987 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1988 + choice.getName());
1989 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1990 String warnmsg = null;
1991 String warnttl = null;
1994 v_client.vclient.storeDocument(choice);
1997 warnttl = "Serious Problem saving Vamsas Document";
1998 warnmsg = ex.toString();
1999 jalview.bin.Cache.log.error("Error Whilst saving document to "
2002 } catch (Exception ex)
2004 warnttl = "Problem saving Vamsas Document.";
2005 warnmsg = ex.toString();
2006 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2010 removeProgressPanel(progpanel);
2011 if (warnmsg != null)
2013 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2015 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2021 JPanel vamUpdate = null;
2024 * hide vamsas user gui bits when a vamsas document event is being handled.
2027 * true to hide gui, false to reveal gui
2029 public void setVamsasUpdate(boolean b)
2031 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2032 + (b ? "in progress" : "finished"));
2034 if (vamUpdate != null)
2036 this.removeProgressPanel(vamUpdate);
2040 vamUpdate = this.addProgressPanel("Updating vamsas session");
2042 vamsasStart.setVisible(!b);
2043 vamsasStop.setVisible(!b);
2044 vamsasSave.setVisible(!b);
2047 public JInternalFrame[] getAllFrames()
2049 return desktop.getAllFrames();
2053 * Checks the given url to see if it gives a response indicating that the user
2054 * should be informed of a new questionnaire.
2058 public void checkForQuestionnaire(String url)
2060 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2061 // javax.swing.SwingUtilities.invokeLater(jvq);
2062 new Thread(jvq).start();
2066 * Proxy class for JDesktopPane which optionally displays the current memory
2067 * usage and highlights the desktop area with a red bar if free memory runs
2072 public class MyDesktopPane extends JDesktopPane implements Runnable
2075 boolean showMemoryUsage = false;
2079 java.text.NumberFormat df;
2081 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2084 public MyDesktopPane(boolean showMemoryUsage)
2086 showMemoryUsage(showMemoryUsage);
2089 public void showMemoryUsage(boolean showMemoryUsage)
2091 this.showMemoryUsage = showMemoryUsage;
2092 if (showMemoryUsage)
2094 Thread worker = new Thread(this);
2099 public boolean isShowMemoryUsage()
2101 return showMemoryUsage;
2106 df = java.text.NumberFormat.getNumberInstance();
2107 df.setMaximumFractionDigits(2);
2108 runtime = Runtime.getRuntime();
2110 while (showMemoryUsage)
2114 maxMemory = runtime.maxMemory() / 1048576f;
2115 allocatedMemory = runtime.totalMemory() / 1048576f;
2116 freeMemory = runtime.freeMemory() / 1048576f;
2117 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2119 percentUsage = (totalFreeMemory / maxMemory) * 100;
2121 // if (percentUsage < 20)
2123 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2125 // instance.set.setBorder(border1);
2128 // sleep after showing usage
2130 } catch (Exception ex)
2132 ex.printStackTrace();
2137 public void paintComponent(Graphics g)
2139 if (showMemoryUsage && g != null && df != null)
2141 if (percentUsage < 20)
2142 g.setColor(Color.red);
2143 FontMetrics fm = g.getFontMetrics();
2147 MessageManager.formatMessage("label.memory_stats", new String[]{df.format(totalFreeMemory),df.format(maxMemory),df.format(percentUsage)}), 10,
2148 getHeight() - fm.getHeight());
2155 * fixes stacking order after a modal dialog to ensure windows that should be
2156 * on top actually are
2158 public void relayerWindows()
2163 protected JMenuItem groovyShell;
2165 public void doGroovyCheck()
2167 if (jalview.bin.Cache.groovyJarsPresent())
2169 groovyShell = new JMenuItem();
2170 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2171 groovyShell.addActionListener(new ActionListener()
2173 public void actionPerformed(ActionEvent e)
2175 groovyShell_actionPerformed(e);
2178 toolsMenu.add(groovyShell);
2179 groovyShell.setVisible(true);
2184 * Accessor method to quickly get all the AlignmentFrames loaded.
2186 public static AlignFrame[] getAlignframes()
2188 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2194 Vector avp = new Vector();
2198 for (int i = frames.length - 1; i > -1; i--)
2200 if (frames[i] instanceof AlignFrame)
2202 AlignFrame af = (AlignFrame) frames[i];
2206 } catch (Exception ex)
2208 ex.printStackTrace();
2210 if (avp.size() == 0)
2214 AlignFrame afs[] = new AlignFrame[avp.size()];
2215 for (int i = 0, j = avp.size(); i < j; i++)
2217 afs[i] = (AlignFrame) avp.elementAt(i);
2223 public AppJmol[] getJmols()
2225 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2231 Vector avp = new Vector();
2235 for (int i = frames.length - 1; i > -1; i--)
2237 if (frames[i] instanceof AppJmol)
2239 AppJmol af = (AppJmol) frames[i];
2243 } catch (Exception ex)
2245 ex.printStackTrace();
2247 if (avp.size() == 0)
2251 AppJmol afs[] = new AppJmol[avp.size()];
2252 for (int i = 0, j = avp.size(); i < j; i++)
2254 afs[i] = (AppJmol) avp.elementAt(i);
2261 * Add Groovy Support to Jalview
2263 public void groovyShell_actionPerformed(ActionEvent e)
2265 // use reflection to avoid creating compilation dependency.
2266 if (!jalview.bin.Cache.groovyJarsPresent())
2269 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2273 Class gcClass = Desktop.class.getClassLoader().loadClass(
2274 "groovy.ui.Console");
2275 Constructor gccons = gcClass.getConstructor(null);
2276 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2278 { String.class, Object.class });
2279 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2280 Object gc = gccons.newInstance(null);
2281 setvar.invoke(gc, new Object[]
2282 { "Jalview", this });
2283 run.invoke(gc, null);
2284 } catch (Exception ex)
2286 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2288 .showInternalMessageDialog(
2291 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2292 "Jalview Groovy Support Failed",
2293 JOptionPane.ERROR_MESSAGE);
2298 * Progress bars managed by the IProgressIndicator method.
2300 private Hashtable<Long, JPanel> progressBars;
2302 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2307 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2309 public void setProgressBar(String message, long id)
2311 if (progressBars == null)
2313 progressBars = new Hashtable<Long, JPanel>();
2314 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2317 if (progressBars.get(new Long(id)) != null)
2319 JPanel progressPanel = progressBars.remove(new Long(id));
2320 if (progressBarHandlers.contains(new Long(id)))
2322 progressBarHandlers.remove(new Long(id));
2324 removeProgressPanel(progressPanel);
2328 progressBars.put(new Long(id), addProgressPanel(message));
2335 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2336 * jalview.gui.IProgressIndicatorHandler)
2338 public void registerHandler(final long id,
2339 final IProgressIndicatorHandler handler)
2341 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2344 "call setProgressBar before registering the progress bar's handler.");
2346 progressBarHandlers.put(new Long(id), handler);
2347 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2348 if (handler.canCancel())
2350 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
2351 final IProgressIndicator us = this;
2352 cancel.addActionListener(new ActionListener()
2355 public void actionPerformed(ActionEvent e)
2357 handler.cancelActivity(id);
2360 + ((JLabel) progressPanel.getComponent(0))
2364 progressPanel.add(cancel, BorderLayout.EAST);
2370 * @return true if any progress bars are still active
2373 public boolean operationInProgress()
2375 if (progressBars != null && progressBars.size() > 0)
2383 * This will return the first AlignFrame viewing AlignViewport av. It will
2384 * break if there are more than one AlignFrames viewing a particular av. This
2387 * @return alignFrame for av
2389 public static AlignFrame getAlignFrameFor(AlignViewport av)
2391 if (desktop != null)
2393 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2394 for (int panel = 0; aps != null && panel < aps.length; panel++)
2396 if (aps[panel] != null && aps[panel].av == av)
2398 return aps[panel].alignFrame;
2405 public VamsasApplication getVamsasApplication()
2412 * flag set if jalview GUI is being operated programmatically
2414 private boolean inBatchMode = false;
2417 * check if jalview GUI is being operated programmatically
2419 * @return inBatchMode
2421 public boolean isInBatchMode()
2427 * set flag if jalview GUI is being operated programmatically
2429 * @param inBatchMode
2431 public void setInBatchMode(boolean inBatchMode)
2433 this.inBatchMode = inBatchMode;
2436 public void startServiceDiscovery()
2438 startServiceDiscovery(false);
2441 public void startServiceDiscovery(boolean blocking)
2443 boolean alive = true;
2444 Thread t0 = null, t1 = null, t2 = null;
2445 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2448 // todo: changesupport handlers need to be transferred
2449 if (discoverer == null)
2451 discoverer = new jalview.ws.jws1.Discoverer();
2452 // register PCS handler for desktop.
2453 discoverer.addPropertyChangeListener(changeSupport);
2455 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2456 // until we phase out completely
2457 (t0 = new Thread(discoverer)).start();
2460 // ENFIN services are EOLed as of Jalview 2.8.1 release
2465 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2467 // EnfinEnvision web service menu entries are rebuild every time the
2468 // menu is shown, so no changeSupport events are needed.
2469 jalview.ws.EnfinEnvision2OneWay.getInstance();
2470 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2473 } catch (Exception e)
2476 .info("Exception when trying to launch Envision2 workflow discovery.",
2478 Cache.log.info(e.getStackTrace());
2482 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2484 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2486 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2488 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2494 // TODO: do rest service discovery
2503 } catch (Exception e)
2506 alive = (t1 != null && t1.isAlive())
2507 || (t2 != null && t2.isAlive())
2508 || (t3 != null && t3.isAlive())
2509 || (t0 != null && t0.isAlive());
2515 * called to check if the service discovery process completed successfully.
2519 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2521 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2523 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2524 .getErrorMessages();
2527 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2529 if (serviceChangedDialog == null)
2531 // only run if we aren't already displaying one of these.
2532 addDialogThread(serviceChangedDialog = new Runnable()
2538 * JalviewDialog jd =new JalviewDialog() {
2540 * @Override protected void cancelPressed() { // TODO
2541 * Auto-generated method stub
2543 * }@Override protected void okPressed() { // TODO
2544 * Auto-generated method stub
2546 * }@Override protected void raiseClosed() { // TODO
2547 * Auto-generated method stub
2549 * } }; jd.initDialogFrame(new
2550 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2551 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2552 * + " or mis-configured HTTP proxy settings.<br/>" +
2553 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2555 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2556 * ), true, true, "Web Service Configuration Problem", 450,
2559 * jd.waitForInput();
2565 "<html><table width=\"450\"><tr><td>"
2567 + "</td></tr></table>"
2568 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2569 + " or mis-configured HTTP proxy settings.</p>"
2570 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2571 + " Tools->Preferences dialog box to change them.</p></html>"),
2572 "Web Service Configuration Problem",
2573 JOptionPane.DEFAULT_OPTION,
2574 JOptionPane.ERROR_MESSAGE);
2575 serviceChangedDialog = null;
2584 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2591 private Runnable serviceChangedDialog = null;
2594 * start a thread to open a URL in the configured browser. Pops up a warning
2595 * dialog to the user if there is an exception when calling out to the browser
2600 public static void showUrl(final String url)
2602 showUrl(url, Desktop.instance);
2606 * Like showUrl but allows progress handler to be specified
2610 * (null) or object implementing IProgressIndicator
2612 public static void showUrl(final String url,
2613 final IProgressIndicator progress)
2615 new Thread(new Runnable()
2621 if (progress != null)
2623 progress.setProgressBar("Opening " + url, this.hashCode());
2625 jalview.util.BrowserLauncher.openURL(url);
2626 } catch (Exception ex)
2629 .showInternalMessageDialog(
2631 "Unixers: Couldn't find default web browser."
2632 + "\nAdd the full path to your browser in Preferences.",
2633 "Web browser not found",
2634 JOptionPane.WARNING_MESSAGE);
2636 ex.printStackTrace();
2638 if (progress != null)
2640 progress.setProgressBar(null, this.hashCode());
2646 public static WsParamSetManager wsparamManager = null;
2648 public static ParamManager getUserParameterStore()
2650 if (wsparamManager == null)
2652 wsparamManager = new WsParamSetManager();
2654 return wsparamManager;
2658 * static hyperlink handler proxy method for use by Jalview's internal windows
2662 public static void hyperlinkUpdate(HyperlinkEvent e)
2664 if (e.getEventType() == EventType.ACTIVATED)
2669 url = e.getURL().toString();
2670 Desktop.showUrl(url);
2671 } catch (Exception x)
2675 if (Cache.log != null)
2677 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2681 System.err.println("Couldn't handle string " + url
2685 // ignore any exceptions due to dud links.
2692 * single thread that handles display of dialogs to user.
2694 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2697 * flag indicating if dialogExecutor should try to acquire a permit
2699 private volatile boolean dialogPause = true;
2704 private java.util.concurrent.Semaphore block = new Semaphore(0);
2707 * add another dialog thread to the queue
2711 public void addDialogThread(final Runnable prompter)
2713 dialogExecutor.submit(new Runnable()
2722 } catch (InterruptedException x)
2727 if (instance == null)
2733 SwingUtilities.invokeAndWait(prompter);
2734 } catch (Exception q)
2736 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2742 public void startDialogQueue()
2744 // set the flag so we don't pause waiting for another permit and semaphore
2745 // the current task to begin
2746 dialogPause = false;