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 Transferable t = evt.getTransferable();
811 java.util.List files = null;
812 java.util.List protocols = null;
816 DataFlavor uriListFlavor = new DataFlavor(
817 "text/uri-list;class=java.lang.String");
818 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
820 // Works on Windows and MacOSX
821 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
822 files = (java.util.List) t
823 .getTransferData(DataFlavor.javaFileListFlavor);
825 else if (t.isDataFlavorSupported(uriListFlavor))
827 // This is used by Unix drag system
828 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
829 String data = (String) t.getTransferData(uriListFlavor);
830 files = new java.util.ArrayList(1);
831 protocols = new java.util.ArrayList(1);
832 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
833 data, "\r\n"); st.hasMoreTokens();)
835 String s = st.nextToken();
836 if (s.startsWith("#"))
838 // the line is a comment (as per the RFC 2483)
841 java.net.URI uri = new java.net.URI(s);
842 if (uri.getScheme().toLowerCase().startsWith("http"))
844 protocols.add(FormatAdapter.URL);
845 files.add(uri.toString());
849 // otherwise preserve old behaviour: catch all for file objects
850 java.io.File file = new java.io.File(uri);
851 protocols.add(FormatAdapter.FILE);
852 files.add(file.toString());
856 } catch (Exception e)
864 for (int i = 0; i < files.size(); i++)
866 String file = files.get(i).toString();
867 String protocol = (protocols == null) ? FormatAdapter.FILE
868 : (String) protocols.get(i);
869 String format = null;
871 if (file.endsWith(".jar"))
878 format = new IdentifyFile().Identify(file, protocol);
881 new FileLoader().LoadFile(file, protocol, format);
884 } catch (Exception ex)
896 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
898 JalviewFileChooser chooser = new JalviewFileChooser(
899 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
900 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
901 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
902 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
904 chooser.setFileView(new JalviewFileView());
905 chooser.setDialogTitle(MessageManager.getString("label.open_local_file"));
906 chooser.setToolTipText(MessageManager.getString("action.open"));
908 int value = chooser.showOpenDialog(this);
910 if (value == JalviewFileChooser.APPROVE_OPTION)
912 String choice = chooser.getSelectedFile().getPath();
913 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
914 .getSelectedFile().getParent());
916 String format = null;
917 if (chooser.getSelectedFormat()!=null && chooser.getSelectedFormat().equals("Jalview"))
923 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
926 if (viewport != null)
928 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
933 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
944 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
946 // This construct allows us to have a wider textfield
948 JLabel label = new JLabel(MessageManager.getString("label.input_file_url"));
949 final JComboBox history = new JComboBox();
951 JPanel panel = new JPanel(new GridLayout(2, 1));
954 history.setPreferredSize(new Dimension(400, 20));
955 history.setEditable(true);
956 history.addItem("http://www.");
958 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
962 if (historyItems != null)
964 st = new StringTokenizer(historyItems, "\t");
966 while (st.hasMoreTokens())
968 history.addItem(st.nextElement());
972 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
973 MessageManager.getString("label.input_alignment_from_url"), JOptionPane.OK_CANCEL_OPTION);
975 if (reply != JOptionPane.OK_OPTION)
980 String url = history.getSelectedItem().toString();
982 if (url.toLowerCase().endsWith(".jar"))
984 if (viewport != null)
986 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
991 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
996 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
998 if (format.equals("URL NOT FOUND"))
1000 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1001 "Couldn't locate " + url, "URL not found",
1002 JOptionPane.WARNING_MESSAGE);
1007 if (viewport != null)
1009 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1013 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1024 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1026 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1027 cap.setForInput(viewport);
1028 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
1036 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1038 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1039 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1041 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1042 getBounds().y, getWidth(), getHeight()));
1044 if (jconsole != null)
1046 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1047 jconsole.stopConsole();
1051 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1054 if (dialogExecutor != null)
1056 dialogExecutor.shutdownNow();
1062 private void storeLastKnownDimensions(String string, Rectangle jc)
1064 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1065 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1066 + " height:" + jc.height);
1068 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1069 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1070 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1071 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1080 public void aboutMenuItem_actionPerformed(ActionEvent e)
1082 // StringBuffer message = getAboutMessage(false);
1083 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1085 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1086 new Thread(new Runnable()
1090 new SplashScreen(true);
1095 public StringBuffer getAboutMessage(boolean shortv)
1097 StringBuffer message = new StringBuffer();
1098 message.append("<html>");
1101 message.append("<h1><strong>Version: "
1102 + jalview.bin.Cache.getProperty("VERSION")
1103 + "</strong></h1><br>");
1104 message.append("<strong>Last Updated: <em>"
1105 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1106 + "</em></strong>");
1112 message.append("<strong>Version "
1113 + jalview.bin.Cache.getProperty("VERSION")
1114 + "; last updated: "
1115 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1118 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1121 message.append("<br>...Checking latest version...</br>");
1123 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1124 .equals(jalview.bin.Cache.getProperty("VERSION")))
1126 boolean red = false;
1127 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1128 .indexOf("automated build") == -1)
1131 // Displayed when code version and jnlp version do not match and code
1132 // version is not a development build
1133 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1136 message.append("<br>!! Version "
1137 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1139 + " is available for download from "
1140 + jalview.bin.Cache.getDefault("www.jalview.org",
1141 "http://www.jalview.org") + " !!");
1144 message.append("</div>");
1147 message.append("<br>Authors: "
1151 "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
1152 + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1153 + "<br>For help, see the FAQ at <a href=\"http://www.jalview.org\">www.jalview.org</a> and/or join the jalview-discuss@jalview.org mailing list"
1154 + "<br>If you use Jalview, please cite:"
1155 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1156 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1157 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1168 public void documentationMenuItem_actionPerformed(ActionEvent e)
1172 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1173 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1174 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1176 javax.help.HelpBroker hb = hs.createHelpBroker();
1177 hb.setCurrentID("home");
1178 hb.setDisplayed(true);
1179 } catch (Exception ex)
1184 public void closeAll_actionPerformed(ActionEvent e)
1186 JInternalFrame[] frames = desktop.getAllFrames();
1187 for (int i = 0; i < frames.length; i++)
1191 frames[i].setClosed(true);
1192 } catch (java.beans.PropertyVetoException ex)
1196 System.out.println("ALL CLOSED");
1197 if (v_client != null)
1199 // TODO clear binding to vamsas document objects on close_all
1204 public void raiseRelated_actionPerformed(ActionEvent e)
1206 reorderAssociatedWindows(false, false);
1209 public void minimizeAssociated_actionPerformed(ActionEvent e)
1211 reorderAssociatedWindows(true, false);
1214 void closeAssociatedWindows()
1216 reorderAssociatedWindows(false, true);
1222 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1225 protected void garbageCollect_actionPerformed(ActionEvent e)
1227 // We simply collect the garbage
1228 jalview.bin.Cache.log.debug("Collecting garbage...");
1230 jalview.bin.Cache.log.debug("Finished garbage collection.");
1237 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1240 protected void showMemusage_actionPerformed(ActionEvent e)
1242 desktop.showMemoryUsage(showMemusage.isSelected());
1249 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1252 protected void showConsole_actionPerformed(ActionEvent e)
1254 showConsole(showConsole.isSelected());
1257 Console jconsole = null;
1260 * control whether the java console is visible or not
1264 void showConsole(boolean selected)
1266 showConsole.setSelected(selected);
1267 // TODO: decide if we should update properties file
1268 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1270 jconsole.setVisible(selected);
1273 void reorderAssociatedWindows(boolean minimize, boolean close)
1275 JInternalFrame[] frames = desktop.getAllFrames();
1276 if (frames == null || frames.length < 1)
1281 AlignViewport source = null, target = null;
1282 if (frames[0] instanceof AlignFrame)
1284 source = ((AlignFrame) frames[0]).getCurrentView();
1286 else if (frames[0] instanceof TreePanel)
1288 source = ((TreePanel) frames[0]).getViewPort();
1290 else if (frames[0] instanceof PCAPanel)
1292 source = ((PCAPanel) frames[0]).av;
1294 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1296 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1301 for (int i = 0; i < frames.length; i++)
1304 if (frames[i] == null)
1308 if (frames[i] instanceof AlignFrame)
1310 target = ((AlignFrame) frames[i]).getCurrentView();
1312 else if (frames[i] instanceof TreePanel)
1314 target = ((TreePanel) frames[i]).getViewPort();
1316 else if (frames[i] instanceof PCAPanel)
1318 target = ((PCAPanel) frames[i]).av;
1320 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1322 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1325 if (source == target)
1331 frames[i].setClosed(true);
1335 frames[i].setIcon(minimize);
1338 frames[i].toFront();
1342 } catch (java.beans.PropertyVetoException ex)
1356 protected void preferences_actionPerformed(ActionEvent e)
1367 public void saveState_actionPerformed(ActionEvent e)
1369 JalviewFileChooser chooser = new JalviewFileChooser(
1370 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1371 { "jar" }, new String[]
1372 { "Jalview Project" }, "Jalview Project");
1374 chooser.setFileView(new JalviewFileView());
1375 chooser.setDialogTitle("Save State");
1377 int value = chooser.showSaveDialog(this);
1379 if (value == JalviewFileChooser.APPROVE_OPTION)
1381 final Desktop me = this;
1382 final java.io.File choice = chooser.getSelectedFile();
1383 new Thread(new Runnable()
1388 setProgressBar("Saving jalview project " + choice.getName(),
1390 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1391 choice.getParent());
1392 // TODO catch and handle errors for savestate
1393 // TODO prevent user from messing with the Desktop whilst we're saving
1396 new Jalview2XML().SaveState(choice);
1397 } catch (OutOfMemoryError oom)
1399 new OOMWarning("Whilst saving current state to "
1400 + choice.getName(), oom);
1401 } catch (Exception ex)
1404 "Problems whilst trying to save to " + choice.getName(),
1406 JOptionPane.showMessageDialog(
1408 "Error whilst saving current state to "
1409 + choice.getName(), "Couldn't save project",
1410 JOptionPane.WARNING_MESSAGE);
1412 setProgressBar(null, choice.hashCode());
1424 public void loadState_actionPerformed(ActionEvent e)
1426 JalviewFileChooser chooser = new JalviewFileChooser(
1427 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1428 { "jar" }, new String[]
1429 { "Jalview Project" }, "Jalview Project");
1430 chooser.setFileView(new JalviewFileView());
1431 chooser.setDialogTitle("Restore state");
1433 int value = chooser.showOpenDialog(this);
1435 if (value == JalviewFileChooser.APPROVE_OPTION)
1437 final String choice = chooser.getSelectedFile().getAbsolutePath();
1438 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1439 .getSelectedFile().getParent());
1440 new Thread(new Runnable()
1444 setProgressBar("loading jalview project " + choice,
1448 new Jalview2XML().LoadJalviewAlign(choice);
1449 } catch (OutOfMemoryError oom)
1451 new OOMWarning("Whilst loading project from " + choice, oom);
1452 } catch (Exception ex)
1454 Cache.log.error("Problems whilst loading project from "
1456 JOptionPane.showMessageDialog(Desktop.desktop,
1457 "Error whilst loading project from " + choice,
1458 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1460 setProgressBar(null, choice.hashCode());
1466 public void inputSequence_actionPerformed(ActionEvent e)
1468 new SequenceFetcher(this);
1471 JPanel progressPanel;
1473 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1475 public void startLoading(final String fileName)
1477 if (fileLoadingCount == 0)
1479 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1485 private JPanel addProgressPanel(String string)
1487 if (progressPanel == null)
1489 progressPanel = new JPanel(new GridLayout(1, 1));
1490 totalProgressCount = 0;
1491 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1493 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1494 JProgressBar progressBar = new JProgressBar();
1495 progressBar.setIndeterminate(true);
1497 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1499 thisprogress.add(progressBar, BorderLayout.CENTER);
1500 progressPanel.add(thisprogress);
1501 ((GridLayout) progressPanel.getLayout())
1502 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1503 ++totalProgressCount;
1504 instance.validate();
1505 return thisprogress;
1508 int totalProgressCount = 0;
1510 private void removeProgressPanel(JPanel progbar)
1512 if (progressPanel != null)
1514 synchronized(progressPanel) {
1515 progressPanel.remove(progbar);
1516 GridLayout gl = (GridLayout) progressPanel.getLayout();
1517 gl.setRows(gl.getRows() - 1);
1518 if (--totalProgressCount < 1)
1520 this.getContentPane().remove(progressPanel);
1521 progressPanel = null;
1528 public void stopLoading()
1531 if (fileLoadingCount < 1)
1533 while (fileLoadingPanels.size()>0)
1535 removeProgressPanel(fileLoadingPanels.remove(0));
1537 fileLoadingPanels.clear();
1538 fileLoadingCount = 0;
1543 public static int getViewCount(String alignmentId)
1545 AlignViewport[] aps = getViewports(alignmentId);
1546 return (aps == null) ? 0 : aps.length;
1551 * @param alignmentId
1552 * @return all AlignmentPanels concerning the alignmentId sequence set
1554 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1557 if (Desktop.desktop == null)
1559 // no frames created and in headless mode
1560 // TODO: verify that frames are recoverable when in headless mode
1563 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1564 ArrayList aps = new ArrayList();
1565 for (int t = 0; t < frames.length; t++)
1567 if (frames[t] instanceof AlignFrame)
1569 AlignFrame af = (AlignFrame) frames[t];
1570 for (int a = 0; a < af.alignPanels.size(); a++)
1572 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1573 .elementAt(a)).av.getSequenceSetId()))
1575 aps.add(af.alignPanels.elementAt(a));
1580 if (aps.size() == 0)
1584 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1585 for (int t = 0; t < vap.length; t++)
1587 vap[t] = (AlignmentPanel) aps.get(t);
1593 * get all the viewports on an alignment.
1595 * @param sequenceSetId
1596 * unique alignment id
1597 * @return all viewports on the alignment bound to sequenceSetId
1599 public static AlignViewport[] getViewports(String sequenceSetId)
1601 Vector viewp = new Vector();
1602 if (desktop != null)
1604 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1606 for (int t = 0; t < frames.length; t++)
1608 if (frames[t] instanceof AlignFrame)
1610 AlignFrame afr = ((AlignFrame) frames[t]);
1611 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1613 if (afr.alignPanels != null)
1615 for (int a = 0; a < afr.alignPanels.size(); a++)
1617 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1618 .elementAt(a)).av.getSequenceSetId()))
1620 viewp.addElement(((AlignmentPanel) afr.alignPanels
1627 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1632 if (viewp.size() > 0)
1634 AlignViewport[] vp = new AlignViewport[viewp.size()];
1642 public void explodeViews(AlignFrame af)
1644 int size = af.alignPanels.size();
1650 for (int i = 0; i < size; i++)
1652 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1653 AlignFrame newaf = new AlignFrame(ap);
1654 if (ap.av.explodedPosition != null
1655 && !ap.av.explodedPosition.equals(af.getBounds()))
1657 newaf.setBounds(ap.av.explodedPosition);
1660 ap.av.gatherViewsHere = false;
1662 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1663 AlignFrame.DEFAULT_HEIGHT);
1666 af.alignPanels.clear();
1667 af.closeMenuItem_actionPerformed(true);
1671 public void gatherViews(AlignFrame source)
1673 source.viewport.gatherViewsHere = true;
1674 source.viewport.explodedPosition = source.getBounds();
1675 JInternalFrame[] frames = desktop.getAllFrames();
1676 String viewId = source.viewport.getSequenceSetId();
1678 for (int t = 0; t < frames.length; t++)
1680 if (frames[t] instanceof AlignFrame && frames[t] != source)
1682 AlignFrame af = (AlignFrame) frames[t];
1683 boolean gatherThis = false;
1684 for (int a = 0; a < af.alignPanels.size(); a++)
1686 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1687 if (viewId.equals(ap.av.getSequenceSetId()))
1690 ap.av.gatherViewsHere = false;
1691 ap.av.explodedPosition = af.getBounds();
1692 source.addAlignmentPanel(ap, false);
1698 af.alignPanels.clear();
1699 af.closeMenuItem_actionPerformed(true);
1706 jalview.gui.VamsasApplication v_client = null;
1708 public void vamsasImport_actionPerformed(ActionEvent e)
1710 if (v_client == null)
1712 // Load and try to start a session.
1713 JalviewFileChooser chooser = new JalviewFileChooser(
1714 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1716 chooser.setFileView(new JalviewFileView());
1717 chooser.setDialogTitle("Open a saved VAMSAS session");
1718 chooser.setToolTipText(MessageManager.getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1720 int value = chooser.showOpenDialog(this);
1722 if (value == JalviewFileChooser.APPROVE_OPTION)
1724 String fle = chooser.getSelectedFile().toString();
1725 if (!vamsasImport(chooser.getSelectedFile()))
1727 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1728 MessageManager.formatMessage("label.couldnt_import_as_vamsas_session", new String[]{fle}),
1729 MessageManager.getString("label.vamsas_document_import_failed"),
1730 JOptionPane.ERROR_MESSAGE);
1736 jalview.bin.Cache.log
1737 .error("Implementation error - load session from a running session is not supported.");
1742 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1745 * @return true if import was a success and a session was started.
1747 public boolean vamsasImport(URL url)
1749 // TODO: create progress bar
1750 if (v_client != null)
1753 jalview.bin.Cache.log
1754 .error("Implementation error - load session from a running session is not supported.");
1760 // copy the URL content to a temporary local file
1761 // TODO: be a bit cleverer here with nio (?!)
1762 File file = File.createTempFile("vdocfromurl", ".vdj");
1763 FileOutputStream fos = new FileOutputStream(file);
1764 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1765 byte[] buffer = new byte[2048];
1767 while ((ln = bis.read(buffer)) > -1)
1769 fos.write(buffer, 0, ln);
1773 v_client = new jalview.gui.VamsasApplication(this, file,
1774 url.toExternalForm());
1775 } catch (Exception ex)
1777 jalview.bin.Cache.log.error(
1778 "Failed to create new vamsas session from contents of URL "
1782 setupVamsasConnectedGui();
1783 v_client.initial_update(); // TODO: thread ?
1784 return v_client.inSession();
1788 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1791 * @return true if import was a success and a session was started.
1793 public boolean vamsasImport(File file)
1795 if (v_client != null)
1798 jalview.bin.Cache.log
1799 .error("Implementation error - load session from a running session is not supported.");
1803 setProgressBar("Importing VAMSAS session from " + file.getName(),
1807 v_client = new jalview.gui.VamsasApplication(this, file, null);
1808 } catch (Exception ex)
1810 setProgressBar("Importing VAMSAS session from " + file.getName(),
1812 jalview.bin.Cache.log.error(
1813 "New vamsas session from existing session file failed:", ex);
1816 setupVamsasConnectedGui();
1817 v_client.initial_update(); // TODO: thread ?
1818 setProgressBar("Importing VAMSAS session from " + file.getName(),
1820 return v_client.inSession();
1823 public boolean joinVamsasSession(String mysesid)
1825 if (v_client != null)
1828 "Trying to join a vamsas session when another is already connected.");
1830 if (mysesid == null)
1832 throw new Error("Invalid vamsas session id.");
1834 v_client = new VamsasApplication(this, mysesid);
1835 setupVamsasConnectedGui();
1836 v_client.initial_update();
1837 return (v_client.inSession());
1840 public void vamsasStart_actionPerformed(ActionEvent e)
1842 if (v_client == null)
1845 // we just start a default session for moment.
1847 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1848 * getProperty("LAST_DIRECTORY"));
1850 * chooser.setFileView(new JalviewFileView());
1851 * chooser.setDialogTitle("Load Vamsas file");
1852 * chooser.setToolTipText("Import");
1854 * int value = chooser.showOpenDialog(this);
1856 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1857 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1859 v_client = new VamsasApplication(this);
1860 setupVamsasConnectedGui();
1861 v_client.initial_update(); // TODO: thread ?
1865 // store current data in session.
1866 v_client.push_update(); // TODO: thread
1870 protected void setupVamsasConnectedGui()
1872 vamsasStart.setText(MessageManager.getString("label.session_update"));
1873 vamsasSave.setVisible(true);
1874 vamsasStop.setVisible(true);
1875 vamsasImport.setVisible(false); // Document import to existing session is
1876 // not possible for vamsas-client-1.0.
1879 protected void setupVamsasDisconnectedGui()
1881 vamsasSave.setVisible(false);
1882 vamsasStop.setVisible(false);
1883 vamsasImport.setVisible(true);
1884 vamsasStart.setText(MessageManager.getString("label.new_vamsas_session"));
1887 public void vamsasStop_actionPerformed(ActionEvent e)
1889 if (v_client != null)
1891 v_client.end_session();
1893 setupVamsasDisconnectedGui();
1897 protected void buildVamsasStMenu()
1899 if (v_client == null)
1901 String[] sess = null;
1904 sess = VamsasApplication.getSessionList();
1905 } catch (Exception e)
1907 jalview.bin.Cache.log.warn(
1908 "Problem getting current sessions list.", e);
1913 jalview.bin.Cache.log.debug("Got current sessions list: "
1914 + sess.length + " entries.");
1915 VamsasStMenu.removeAll();
1916 for (int i = 0; i < sess.length; i++)
1918 JMenuItem sessit = new JMenuItem();
1919 sessit.setText(sess[i]);
1920 sessit.setToolTipText(MessageManager.formatMessage("label.connect_to_session", new String[]{sess[i]}));
1921 final Desktop dsktp = this;
1922 final String mysesid = sess[i];
1923 sessit.addActionListener(new ActionListener()
1926 public void actionPerformed(ActionEvent e)
1928 if (dsktp.v_client == null)
1930 Thread rthr = new Thread(new Runnable()
1935 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1936 dsktp.setupVamsasConnectedGui();
1937 dsktp.v_client.initial_update();
1945 VamsasStMenu.add(sessit);
1947 // don't show an empty menu.
1948 VamsasStMenu.setVisible(sess.length > 0);
1953 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1954 VamsasStMenu.removeAll();
1955 VamsasStMenu.setVisible(false);
1960 // Not interested in the content. Just hide ourselves.
1961 VamsasStMenu.setVisible(false);
1965 public void vamsasSave_actionPerformed(ActionEvent e)
1967 if (v_client != null)
1969 JalviewFileChooser chooser = new JalviewFileChooser(
1970 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1971 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1973 { "Vamsas Document" }, "Vamsas Document");
1975 chooser.setFileView(new JalviewFileView());
1976 chooser.setDialogTitle("Save Vamsas Document Archive");
1978 int value = chooser.showSaveDialog(this);
1980 if (value == JalviewFileChooser.APPROVE_OPTION)
1982 java.io.File choice = chooser.getSelectedFile();
1983 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1984 + choice.getName());
1985 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1986 String warnmsg = null;
1987 String warnttl = null;
1990 v_client.vclient.storeDocument(choice);
1993 warnttl = "Serious Problem saving Vamsas Document";
1994 warnmsg = ex.toString();
1995 jalview.bin.Cache.log.error("Error Whilst saving document to "
1998 } catch (Exception ex)
2000 warnttl = "Problem saving Vamsas Document.";
2001 warnmsg = ex.toString();
2002 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2006 removeProgressPanel(progpanel);
2007 if (warnmsg != null)
2009 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2011 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2017 JPanel vamUpdate = null;
2020 * hide vamsas user gui bits when a vamsas document event is being handled.
2023 * true to hide gui, false to reveal gui
2025 public void setVamsasUpdate(boolean b)
2027 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2028 + (b ? "in progress" : "finished"));
2030 if (vamUpdate != null)
2032 this.removeProgressPanel(vamUpdate);
2036 vamUpdate = this.addProgressPanel("Updating vamsas session");
2038 vamsasStart.setVisible(!b);
2039 vamsasStop.setVisible(!b);
2040 vamsasSave.setVisible(!b);
2043 public JInternalFrame[] getAllFrames()
2045 return desktop.getAllFrames();
2049 * Checks the given url to see if it gives a response indicating that the user
2050 * should be informed of a new questionnaire.
2054 public void checkForQuestionnaire(String url)
2056 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2057 // javax.swing.SwingUtilities.invokeLater(jvq);
2058 new Thread(jvq).start();
2062 * Proxy class for JDesktopPane which optionally displays the current memory
2063 * usage and highlights the desktop area with a red bar if free memory runs
2068 public class MyDesktopPane extends JDesktopPane implements Runnable
2071 boolean showMemoryUsage = false;
2075 java.text.NumberFormat df;
2077 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2080 public MyDesktopPane(boolean showMemoryUsage)
2082 showMemoryUsage(showMemoryUsage);
2085 public void showMemoryUsage(boolean showMemoryUsage)
2087 this.showMemoryUsage = showMemoryUsage;
2088 if (showMemoryUsage)
2090 Thread worker = new Thread(this);
2095 public boolean isShowMemoryUsage()
2097 return showMemoryUsage;
2102 df = java.text.NumberFormat.getNumberInstance();
2103 df.setMaximumFractionDigits(2);
2104 runtime = Runtime.getRuntime();
2106 while (showMemoryUsage)
2110 maxMemory = runtime.maxMemory() / 1048576f;
2111 allocatedMemory = runtime.totalMemory() / 1048576f;
2112 freeMemory = runtime.freeMemory() / 1048576f;
2113 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2115 percentUsage = (totalFreeMemory / maxMemory) * 100;
2117 // if (percentUsage < 20)
2119 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2121 // instance.set.setBorder(border1);
2124 // sleep after showing usage
2126 } catch (Exception ex)
2128 ex.printStackTrace();
2133 public void paintComponent(Graphics g)
2135 if (showMemoryUsage && g != null && df != null)
2137 if (percentUsage < 20)
2138 g.setColor(Color.red);
2139 FontMetrics fm = g.getFontMetrics();
2143 MessageManager.formatMessage("label.memory_stats", new String[]{df.format(totalFreeMemory),df.format(maxMemory),df.format(percentUsage)}), 10,
2144 getHeight() - fm.getHeight());
2151 * fixes stacking order after a modal dialog to ensure windows that should be
2152 * on top actually are
2154 public void relayerWindows()
2159 protected JMenuItem groovyShell;
2161 public void doGroovyCheck()
2163 if (jalview.bin.Cache.groovyJarsPresent())
2165 groovyShell = new JMenuItem();
2166 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2167 groovyShell.addActionListener(new ActionListener()
2169 public void actionPerformed(ActionEvent e)
2171 groovyShell_actionPerformed(e);
2174 toolsMenu.add(groovyShell);
2175 groovyShell.setVisible(true);
2180 * Accessor method to quickly get all the AlignmentFrames loaded.
2182 public static AlignFrame[] getAlignframes()
2184 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2190 Vector avp = new Vector();
2194 for (int i = frames.length - 1; i > -1; i--)
2196 if (frames[i] instanceof AlignFrame)
2198 AlignFrame af = (AlignFrame) frames[i];
2202 } catch (Exception ex)
2204 ex.printStackTrace();
2206 if (avp.size() == 0)
2210 AlignFrame afs[] = new AlignFrame[avp.size()];
2211 for (int i = 0, j = avp.size(); i < j; i++)
2213 afs[i] = (AlignFrame) avp.elementAt(i);
2219 public AppJmol[] getJmols()
2221 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2227 Vector avp = new Vector();
2231 for (int i = frames.length - 1; i > -1; i--)
2233 if (frames[i] instanceof AppJmol)
2235 AppJmol af = (AppJmol) frames[i];
2239 } catch (Exception ex)
2241 ex.printStackTrace();
2243 if (avp.size() == 0)
2247 AppJmol afs[] = new AppJmol[avp.size()];
2248 for (int i = 0, j = avp.size(); i < j; i++)
2250 afs[i] = (AppJmol) avp.elementAt(i);
2257 * Add Groovy Support to Jalview
2259 public void groovyShell_actionPerformed(ActionEvent e)
2261 // use reflection to avoid creating compilation dependency.
2262 if (!jalview.bin.Cache.groovyJarsPresent())
2265 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2269 Class gcClass = Desktop.class.getClassLoader().loadClass(
2270 "groovy.ui.Console");
2271 Constructor gccons = gcClass.getConstructor(null);
2272 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2274 { String.class, Object.class });
2275 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2276 Object gc = gccons.newInstance(null);
2277 setvar.invoke(gc, new Object[]
2278 { "Jalview", this });
2279 run.invoke(gc, null);
2280 } catch (Exception ex)
2282 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2284 .showInternalMessageDialog(
2287 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2288 "Jalview Groovy Support Failed",
2289 JOptionPane.ERROR_MESSAGE);
2294 * Progress bars managed by the IProgressIndicator method.
2296 private Hashtable<Long, JPanel> progressBars;
2298 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2303 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2305 public void setProgressBar(String message, long id)
2307 if (progressBars == null)
2309 progressBars = new Hashtable<Long, JPanel>();
2310 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2313 if (progressBars.get(new Long(id)) != null)
2315 JPanel progressPanel = progressBars.remove(new Long(id));
2316 if (progressBarHandlers.contains(new Long(id)))
2318 progressBarHandlers.remove(new Long(id));
2320 removeProgressPanel(progressPanel);
2324 progressBars.put(new Long(id), addProgressPanel(message));
2331 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2332 * jalview.gui.IProgressIndicatorHandler)
2334 public void registerHandler(final long id,
2335 final IProgressIndicatorHandler handler)
2337 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2340 "call setProgressBar before registering the progress bar's handler.");
2342 progressBarHandlers.put(new Long(id), handler);
2343 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2344 if (handler.canCancel())
2346 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
2347 final IProgressIndicator us = this;
2348 cancel.addActionListener(new ActionListener()
2351 public void actionPerformed(ActionEvent e)
2353 handler.cancelActivity(id);
2356 + ((JLabel) progressPanel.getComponent(0))
2360 progressPanel.add(cancel, BorderLayout.EAST);
2366 * @return true if any progress bars are still active
2369 public boolean operationInProgress()
2371 if (progressBars != null && progressBars.size() > 0)
2379 * This will return the first AlignFrame viewing AlignViewport av. It will
2380 * break if there are more than one AlignFrames viewing a particular av. This
2383 * @return alignFrame for av
2385 public static AlignFrame getAlignFrameFor(AlignViewport av)
2387 if (desktop != null)
2389 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2390 for (int panel = 0; aps != null && panel < aps.length; panel++)
2392 if (aps[panel] != null && aps[panel].av == av)
2394 return aps[panel].alignFrame;
2401 public VamsasApplication getVamsasApplication()
2408 * flag set if jalview GUI is being operated programmatically
2410 private boolean inBatchMode = false;
2413 * check if jalview GUI is being operated programmatically
2415 * @return inBatchMode
2417 public boolean isInBatchMode()
2423 * set flag if jalview GUI is being operated programmatically
2425 * @param inBatchMode
2427 public void setInBatchMode(boolean inBatchMode)
2429 this.inBatchMode = inBatchMode;
2432 public void startServiceDiscovery()
2434 startServiceDiscovery(false);
2437 public void startServiceDiscovery(boolean blocking)
2439 boolean alive = true;
2440 Thread t0 = null, t1 = null, t2 = null;
2441 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2444 // todo: changesupport handlers need to be transferred
2445 if (discoverer == null)
2447 discoverer = new jalview.ws.jws1.Discoverer();
2448 // register PCS handler for desktop.
2449 discoverer.addPropertyChangeListener(changeSupport);
2451 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2452 // until we phase out completely
2453 (t0 = new Thread(discoverer)).start();
2456 // ENFIN services are EOLed as of Jalview 2.8.1 release
2461 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2463 // EnfinEnvision web service menu entries are rebuild every time the
2464 // menu is shown, so no changeSupport events are needed.
2465 jalview.ws.EnfinEnvision2OneWay.getInstance();
2466 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2469 } catch (Exception e)
2472 .info("Exception when trying to launch Envision2 workflow discovery.",
2474 Cache.log.info(e.getStackTrace());
2478 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2480 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2482 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2484 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2490 // TODO: do rest service discovery
2499 } catch (Exception e)
2502 alive = (t1 != null && t1.isAlive())
2503 || (t2 != null && t2.isAlive())
2504 || (t3 != null && t3.isAlive())
2505 || (t0 != null && t0.isAlive());
2511 * called to check if the service discovery process completed successfully.
2515 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2517 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2519 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2520 .getErrorMessages();
2523 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2525 if (serviceChangedDialog == null)
2527 // only run if we aren't already displaying one of these.
2528 addDialogThread(serviceChangedDialog = new Runnable()
2534 * JalviewDialog jd =new JalviewDialog() {
2536 * @Override protected void cancelPressed() { // TODO
2537 * Auto-generated method stub
2539 * }@Override protected void okPressed() { // TODO
2540 * Auto-generated method stub
2542 * }@Override protected void raiseClosed() { // TODO
2543 * Auto-generated method stub
2545 * } }; jd.initDialogFrame(new
2546 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2547 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2548 * + " or mis-configured HTTP proxy settings.<br/>" +
2549 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2551 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2552 * ), true, true, "Web Service Configuration Problem", 450,
2555 * jd.waitForInput();
2561 "<html><table width=\"450\"><tr><td>"
2563 + "</td></tr></table>"
2564 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2565 + " or mis-configured HTTP proxy settings.</p>"
2566 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2567 + " Tools->Preferences dialog box to change them.</p></html>"),
2568 "Web Service Configuration Problem",
2569 JOptionPane.DEFAULT_OPTION,
2570 JOptionPane.ERROR_MESSAGE);
2571 serviceChangedDialog = null;
2580 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2587 private Runnable serviceChangedDialog = null;
2590 * start a thread to open a URL in the configured browser. Pops up a warning
2591 * dialog to the user if there is an exception when calling out to the browser
2596 public static void showUrl(final String url)
2598 showUrl(url, Desktop.instance);
2602 * Like showUrl but allows progress handler to be specified
2606 * (null) or object implementing IProgressIndicator
2608 public static void showUrl(final String url,
2609 final IProgressIndicator progress)
2611 new Thread(new Runnable()
2617 if (progress != null)
2619 progress.setProgressBar("Opening " + url, this.hashCode());
2621 jalview.util.BrowserLauncher.openURL(url);
2622 } catch (Exception ex)
2625 .showInternalMessageDialog(
2627 "Unixers: Couldn't find default web browser."
2628 + "\nAdd the full path to your browser in Preferences.",
2629 "Web browser not found",
2630 JOptionPane.WARNING_MESSAGE);
2632 ex.printStackTrace();
2634 if (progress != null)
2636 progress.setProgressBar(null, this.hashCode());
2642 public static WsParamSetManager wsparamManager = null;
2644 public static ParamManager getUserParameterStore()
2646 if (wsparamManager == null)
2648 wsparamManager = new WsParamSetManager();
2650 return wsparamManager;
2654 * static hyperlink handler proxy method for use by Jalview's internal windows
2658 public static void hyperlinkUpdate(HyperlinkEvent e)
2660 if (e.getEventType() == EventType.ACTIVATED)
2665 url = e.getURL().toString();
2666 Desktop.showUrl(url);
2667 } catch (Exception x)
2671 if (Cache.log != null)
2673 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2677 System.err.println("Couldn't handle string " + url
2681 // ignore any exceptions due to dud links.
2688 * single thread that handles display of dialogs to user.
2690 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2693 * flag indicating if dialogExecutor should try to acquire a permit
2695 private volatile boolean dialogPause = true;
2700 private java.util.concurrent.Semaphore block = new Semaphore(0);
2703 * add another dialog thread to the queue
2707 public void addDialogThread(final Runnable prompter)
2709 dialogExecutor.submit(new Runnable()
2718 } catch (InterruptedException x)
2723 if (instance == null)
2729 SwingUtilities.invokeAndWait(prompter);
2730 } catch (Exception q)
2732 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2738 public void startDialogQueue()
2740 // set the flag so we don't pause waiting for another permit and semaphore
2741 // the current task to begin
2742 dialogPause = false;