2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
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 { "jvp" }, 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 { "jvp","jar" }, new String[]
1433 { "Jalview Project", "Jalview Project (old)" }, "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 progressPanel.remove(progbar);
1519 GridLayout gl = (GridLayout) progressPanel.getLayout();
1520 gl.setRows(gl.getRows() - 1);
1521 if (--totalProgressCount < 1)
1523 this.getContentPane().remove(progressPanel);
1524 progressPanel = null;
1530 public void stopLoading()
1533 if (fileLoadingCount < 1)
1535 for (JPanel flp : fileLoadingPanels)
1537 removeProgressPanel(flp);
1539 fileLoadingPanels.clear();
1540 fileLoadingCount = 0;
1545 public static int getViewCount(String alignmentId)
1547 AlignViewport[] aps = getViewports(alignmentId);
1548 return (aps == null) ? 0 : aps.length;
1553 * @param alignmentId
1554 * @return all AlignmentPanels concerning the alignmentId sequence set
1556 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1559 if (Desktop.desktop == null)
1561 // no frames created and in headless mode
1562 // TODO: verify that frames are recoverable when in headless mode
1565 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1566 ArrayList aps = new ArrayList();
1567 for (int t = 0; t < frames.length; t++)
1569 if (frames[t] instanceof AlignFrame)
1571 AlignFrame af = (AlignFrame) frames[t];
1572 for (int a = 0; a < af.alignPanels.size(); a++)
1574 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1575 .elementAt(a)).av.getSequenceSetId()))
1577 aps.add(af.alignPanels.elementAt(a));
1582 if (aps.size() == 0)
1586 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1587 for (int t = 0; t < vap.length; t++)
1589 vap[t] = (AlignmentPanel) aps.get(t);
1595 * get all the viewports on an alignment.
1597 * @param sequenceSetId
1598 * unique alignment id
1599 * @return all viewports on the alignment bound to sequenceSetId
1601 public static AlignViewport[] getViewports(String sequenceSetId)
1603 Vector viewp = new Vector();
1604 if (desktop != null)
1606 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1608 for (int t = 0; t < frames.length; t++)
1610 if (frames[t] instanceof AlignFrame)
1612 AlignFrame afr = ((AlignFrame) frames[t]);
1613 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1615 if (afr.alignPanels != null)
1617 for (int a = 0; a < afr.alignPanels.size(); a++)
1619 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1620 .elementAt(a)).av.getSequenceSetId()))
1622 viewp.addElement(((AlignmentPanel) afr.alignPanels
1629 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1634 if (viewp.size() > 0)
1636 AlignViewport[] vp = new AlignViewport[viewp.size()];
1644 public void explodeViews(AlignFrame af)
1646 int size = af.alignPanels.size();
1652 for (int i = 0; i < size; i++)
1654 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1655 AlignFrame newaf = new AlignFrame(ap);
1656 if (ap.av.explodedPosition != null
1657 && !ap.av.explodedPosition.equals(af.getBounds()))
1659 newaf.setBounds(ap.av.explodedPosition);
1662 ap.av.gatherViewsHere = false;
1664 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1665 AlignFrame.DEFAULT_HEIGHT);
1668 af.alignPanels.clear();
1669 af.closeMenuItem_actionPerformed(true);
1673 public void gatherViews(AlignFrame source)
1675 source.viewport.gatherViewsHere = true;
1676 source.viewport.explodedPosition = source.getBounds();
1677 JInternalFrame[] frames = desktop.getAllFrames();
1678 String viewId = source.viewport.getSequenceSetId();
1680 for (int t = 0; t < frames.length; t++)
1682 if (frames[t] instanceof AlignFrame && frames[t] != source)
1684 AlignFrame af = (AlignFrame) frames[t];
1685 boolean gatherThis = false;
1686 for (int a = 0; a < af.alignPanels.size(); a++)
1688 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1689 if (viewId.equals(ap.av.getSequenceSetId()))
1692 ap.av.gatherViewsHere = false;
1693 ap.av.explodedPosition = af.getBounds();
1694 source.addAlignmentPanel(ap, false);
1700 af.alignPanels.clear();
1701 af.closeMenuItem_actionPerformed(true);
1708 jalview.gui.VamsasApplication v_client = null;
1710 public void vamsasImport_actionPerformed(ActionEvent e)
1712 if (v_client == null)
1714 // Load and try to start a session.
1715 JalviewFileChooser chooser = new JalviewFileChooser(
1716 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1718 chooser.setFileView(new JalviewFileView());
1719 chooser.setDialogTitle("Open a saved VAMSAS session");
1720 chooser.setToolTipText(MessageManager.getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1722 int value = chooser.showOpenDialog(this);
1724 if (value == JalviewFileChooser.APPROVE_OPTION)
1726 String fle = chooser.getSelectedFile().toString();
1727 if (!vamsasImport(chooser.getSelectedFile()))
1729 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1730 MessageManager.formatMessage("label.couldnt_import_as_vamsas_session", new String[]{fle}),
1731 MessageManager.getString("label.vamsas_document_import_failed"),
1732 JOptionPane.ERROR_MESSAGE);
1738 jalview.bin.Cache.log
1739 .error("Implementation error - load session from a running session is not supported.");
1744 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1747 * @return true if import was a success and a session was started.
1749 public boolean vamsasImport(URL url)
1751 // TODO: create progress bar
1752 if (v_client != null)
1755 jalview.bin.Cache.log
1756 .error("Implementation error - load session from a running session is not supported.");
1762 // copy the URL content to a temporary local file
1763 // TODO: be a bit cleverer here with nio (?!)
1764 File file = File.createTempFile("vdocfromurl", ".vdj");
1765 FileOutputStream fos = new FileOutputStream(file);
1766 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1767 byte[] buffer = new byte[2048];
1769 while ((ln = bis.read(buffer)) > -1)
1771 fos.write(buffer, 0, ln);
1775 v_client = new jalview.gui.VamsasApplication(this, file,
1776 url.toExternalForm());
1777 } catch (Exception ex)
1779 jalview.bin.Cache.log.error(
1780 "Failed to create new vamsas session from contents of URL "
1784 setupVamsasConnectedGui();
1785 v_client.initial_update(); // TODO: thread ?
1786 return v_client.inSession();
1790 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1793 * @return true if import was a success and a session was started.
1795 public boolean vamsasImport(File file)
1797 if (v_client != null)
1800 jalview.bin.Cache.log
1801 .error("Implementation error - load session from a running session is not supported.");
1805 setProgressBar("Importing VAMSAS session from " + file.getName(),
1809 v_client = new jalview.gui.VamsasApplication(this, file, null);
1810 } catch (Exception ex)
1812 setProgressBar("Importing VAMSAS session from " + file.getName(),
1814 jalview.bin.Cache.log.error(
1815 "New vamsas session from existing session file failed:", ex);
1818 setupVamsasConnectedGui();
1819 v_client.initial_update(); // TODO: thread ?
1820 setProgressBar("Importing VAMSAS session from " + file.getName(),
1822 return v_client.inSession();
1825 public boolean joinVamsasSession(String mysesid)
1827 if (v_client != null)
1830 "Trying to join a vamsas session when another is already connected.");
1832 if (mysesid == null)
1834 throw new Error("Invalid vamsas session id.");
1836 v_client = new VamsasApplication(this, mysesid);
1837 setupVamsasConnectedGui();
1838 v_client.initial_update();
1839 return (v_client.inSession());
1842 public void vamsasStart_actionPerformed(ActionEvent e)
1844 if (v_client == null)
1847 // we just start a default session for moment.
1849 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1850 * getProperty("LAST_DIRECTORY"));
1852 * chooser.setFileView(new JalviewFileView());
1853 * chooser.setDialogTitle("Load Vamsas file");
1854 * chooser.setToolTipText("Import");
1856 * int value = chooser.showOpenDialog(this);
1858 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1859 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1861 v_client = new VamsasApplication(this);
1862 setupVamsasConnectedGui();
1863 v_client.initial_update(); // TODO: thread ?
1867 // store current data in session.
1868 v_client.push_update(); // TODO: thread
1872 protected void setupVamsasConnectedGui()
1874 vamsasStart.setText(MessageManager.getString("label.session_update"));
1875 vamsasSave.setVisible(true);
1876 vamsasStop.setVisible(true);
1877 vamsasImport.setVisible(false); // Document import to existing session is
1878 // not possible for vamsas-client-1.0.
1881 protected void setupVamsasDisconnectedGui()
1883 vamsasSave.setVisible(false);
1884 vamsasStop.setVisible(false);
1885 vamsasImport.setVisible(true);
1886 vamsasStart.setText(MessageManager.getString("label.new_vamsas_session"));
1889 public void vamsasStop_actionPerformed(ActionEvent e)
1891 if (v_client != null)
1893 v_client.end_session();
1895 setupVamsasDisconnectedGui();
1899 protected void buildVamsasStMenu()
1901 if (v_client == null)
1903 String[] sess = null;
1906 sess = VamsasApplication.getSessionList();
1907 } catch (Exception e)
1909 jalview.bin.Cache.log.warn(
1910 "Problem getting current sessions list.", e);
1915 jalview.bin.Cache.log.debug("Got current sessions list: "
1916 + sess.length + " entries.");
1917 VamsasStMenu.removeAll();
1918 for (int i = 0; i < sess.length; i++)
1920 JMenuItem sessit = new JMenuItem();
1921 sessit.setText(sess[i]);
1922 sessit.setToolTipText(MessageManager.formatMessage("label.connect_to_session", new String[]{sess[i]}));
1923 final Desktop dsktp = this;
1924 final String mysesid = sess[i];
1925 sessit.addActionListener(new ActionListener()
1928 public void actionPerformed(ActionEvent e)
1930 if (dsktp.v_client == null)
1932 Thread rthr = new Thread(new Runnable()
1937 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1938 dsktp.setupVamsasConnectedGui();
1939 dsktp.v_client.initial_update();
1947 VamsasStMenu.add(sessit);
1949 // don't show an empty menu.
1950 VamsasStMenu.setVisible(sess.length > 0);
1955 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1956 VamsasStMenu.removeAll();
1957 VamsasStMenu.setVisible(false);
1962 // Not interested in the content. Just hide ourselves.
1963 VamsasStMenu.setVisible(false);
1967 public void vamsasSave_actionPerformed(ActionEvent e)
1969 if (v_client != null)
1971 JalviewFileChooser chooser = new JalviewFileChooser(
1972 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1973 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1975 { "Vamsas Document" }, "Vamsas Document");
1977 chooser.setFileView(new JalviewFileView());
1978 chooser.setDialogTitle("Save Vamsas Document Archive");
1980 int value = chooser.showSaveDialog(this);
1982 if (value == JalviewFileChooser.APPROVE_OPTION)
1984 java.io.File choice = chooser.getSelectedFile();
1985 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
1986 + choice.getName());
1987 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1988 String warnmsg = null;
1989 String warnttl = null;
1992 v_client.vclient.storeDocument(choice);
1995 warnttl = "Serious Problem saving Vamsas Document";
1996 warnmsg = ex.toString();
1997 jalview.bin.Cache.log.error("Error Whilst saving document to "
2000 } catch (Exception ex)
2002 warnttl = "Problem saving Vamsas Document.";
2003 warnmsg = ex.toString();
2004 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2008 removeProgressPanel(progpanel);
2009 if (warnmsg != null)
2011 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2013 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2019 JPanel vamUpdate = null;
2022 * hide vamsas user gui bits when a vamsas document event is being handled.
2025 * true to hide gui, false to reveal gui
2027 public void setVamsasUpdate(boolean b)
2029 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2030 + (b ? "in progress" : "finished"));
2032 if (vamUpdate != null)
2034 this.removeProgressPanel(vamUpdate);
2038 vamUpdate = this.addProgressPanel("Updating vamsas session");
2040 vamsasStart.setVisible(!b);
2041 vamsasStop.setVisible(!b);
2042 vamsasSave.setVisible(!b);
2045 public JInternalFrame[] getAllFrames()
2047 return desktop.getAllFrames();
2051 * Checks the given url to see if it gives a response indicating that the user
2052 * should be informed of a new questionnaire.
2056 public void checkForQuestionnaire(String url)
2058 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2059 // javax.swing.SwingUtilities.invokeLater(jvq);
2060 new Thread(jvq).start();
2064 * Proxy class for JDesktopPane which optionally displays the current memory
2065 * usage and highlights the desktop area with a red bar if free memory runs
2070 public class MyDesktopPane extends JDesktopPane implements Runnable
2073 boolean showMemoryUsage = false;
2077 java.text.NumberFormat df;
2079 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2082 public MyDesktopPane(boolean showMemoryUsage)
2084 showMemoryUsage(showMemoryUsage);
2087 public void showMemoryUsage(boolean showMemoryUsage)
2089 this.showMemoryUsage = showMemoryUsage;
2090 if (showMemoryUsage)
2092 Thread worker = new Thread(this);
2097 public boolean isShowMemoryUsage()
2099 return showMemoryUsage;
2104 df = java.text.NumberFormat.getNumberInstance();
2105 df.setMaximumFractionDigits(2);
2106 runtime = Runtime.getRuntime();
2108 while (showMemoryUsage)
2112 maxMemory = runtime.maxMemory() / 1048576f;
2113 allocatedMemory = runtime.totalMemory() / 1048576f;
2114 freeMemory = runtime.freeMemory() / 1048576f;
2115 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2117 percentUsage = (totalFreeMemory / maxMemory) * 100;
2119 // if (percentUsage < 20)
2121 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2123 // instance.set.setBorder(border1);
2126 // sleep after showing usage
2128 } catch (Exception ex)
2130 ex.printStackTrace();
2135 public void paintComponent(Graphics g)
2137 if (showMemoryUsage && g != null && df != null)
2139 if (percentUsage < 20)
2140 g.setColor(Color.red);
2141 FontMetrics fm = g.getFontMetrics();
2145 MessageManager.formatMessage("label.memory_stats", new String[]{df.format(totalFreeMemory),df.format(maxMemory),df.format(percentUsage)}), 10,
2146 getHeight() - fm.getHeight());
2153 * fixes stacking order after a modal dialog to ensure windows that should be
2154 * on top actually are
2156 public void relayerWindows()
2161 protected JMenuItem groovyShell;
2163 public void doGroovyCheck()
2165 if (jalview.bin.Cache.groovyJarsPresent())
2167 groovyShell = new JMenuItem();
2168 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2169 groovyShell.addActionListener(new ActionListener()
2171 public void actionPerformed(ActionEvent e)
2173 groovyShell_actionPerformed(e);
2176 toolsMenu.add(groovyShell);
2177 groovyShell.setVisible(true);
2182 * Accessor method to quickly get all the AlignmentFrames loaded.
2184 public static AlignFrame[] getAlignframes()
2186 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2192 Vector avp = new Vector();
2196 for (int i = frames.length - 1; i > -1; i--)
2198 if (frames[i] instanceof AlignFrame)
2200 AlignFrame af = (AlignFrame) frames[i];
2204 } catch (Exception ex)
2206 ex.printStackTrace();
2208 if (avp.size() == 0)
2212 AlignFrame afs[] = new AlignFrame[avp.size()];
2213 for (int i = 0, j = avp.size(); i < j; i++)
2215 afs[i] = (AlignFrame) avp.elementAt(i);
2221 public AppJmol[] getJmols()
2223 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2229 Vector avp = new Vector();
2233 for (int i = frames.length - 1; i > -1; i--)
2235 if (frames[i] instanceof AppJmol)
2237 AppJmol af = (AppJmol) frames[i];
2241 } catch (Exception ex)
2243 ex.printStackTrace();
2245 if (avp.size() == 0)
2249 AppJmol afs[] = new AppJmol[avp.size()];
2250 for (int i = 0, j = avp.size(); i < j; i++)
2252 afs[i] = (AppJmol) avp.elementAt(i);
2259 * Add Groovy Support to Jalview
2261 public void groovyShell_actionPerformed(ActionEvent e)
2263 // use reflection to avoid creating compilation dependency.
2264 if (!jalview.bin.Cache.groovyJarsPresent())
2267 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2271 Class gcClass = Desktop.class.getClassLoader().loadClass(
2272 "groovy.ui.Console");
2273 Constructor gccons = gcClass.getConstructor(null);
2274 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2276 { String.class, Object.class });
2277 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2278 Object gc = gccons.newInstance(null);
2279 setvar.invoke(gc, new Object[]
2280 { "Jalview", this });
2281 run.invoke(gc, null);
2282 } catch (Exception ex)
2284 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2286 .showInternalMessageDialog(
2289 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2290 "Jalview Groovy Support Failed",
2291 JOptionPane.ERROR_MESSAGE);
2296 * Progress bars managed by the IProgressIndicator method.
2298 private Hashtable<Long, JPanel> progressBars;
2300 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2305 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2307 public void setProgressBar(String message, long id)
2309 if (progressBars == null)
2311 progressBars = new Hashtable<Long, JPanel>();
2312 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2315 if (progressBars.get(new Long(id)) != null)
2317 JPanel progressPanel = progressBars.remove(new Long(id));
2318 if (progressBarHandlers.contains(new Long(id)))
2320 progressBarHandlers.remove(new Long(id));
2322 removeProgressPanel(progressPanel);
2326 progressBars.put(new Long(id), addProgressPanel(message));
2333 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2334 * jalview.gui.IProgressIndicatorHandler)
2336 public void registerHandler(final long id,
2337 final IProgressIndicatorHandler handler)
2339 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2342 "call setProgressBar before registering the progress bar's handler.");
2344 progressBarHandlers.put(new Long(id), handler);
2345 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2346 if (handler.canCancel())
2348 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
2349 final IProgressIndicator us = this;
2350 cancel.addActionListener(new ActionListener()
2353 public void actionPerformed(ActionEvent e)
2355 handler.cancelActivity(id);
2358 + ((JLabel) progressPanel.getComponent(0))
2362 progressPanel.add(cancel, BorderLayout.EAST);
2368 * @return true if any progress bars are still active
2371 public boolean operationInProgress()
2373 if (progressBars != null && progressBars.size() > 0)
2381 * This will return the first AlignFrame viewing AlignViewport av. It will
2382 * break if there are more than one AlignFrames viewing a particular av. This
2385 * @return alignFrame for av
2387 public static AlignFrame getAlignFrameFor(AlignViewport av)
2389 if (desktop != null)
2391 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2392 for (int panel = 0; aps != null && panel < aps.length; panel++)
2394 if (aps[panel] != null && aps[panel].av == av)
2396 return aps[panel].alignFrame;
2403 public VamsasApplication getVamsasApplication()
2410 * flag set if jalview GUI is being operated programmatically
2412 private boolean inBatchMode = false;
2415 * check if jalview GUI is being operated programmatically
2417 * @return inBatchMode
2419 public boolean isInBatchMode()
2425 * set flag if jalview GUI is being operated programmatically
2427 * @param inBatchMode
2429 public void setInBatchMode(boolean inBatchMode)
2431 this.inBatchMode = inBatchMode;
2434 public void startServiceDiscovery()
2436 startServiceDiscovery(false);
2439 public void startServiceDiscovery(boolean blocking)
2441 boolean alive = true;
2442 Thread t0 = null, t1 = null, t2 = null;
2443 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2446 // todo: changesupport handlers need to be transferred
2447 if (discoverer == null)
2449 discoverer = new jalview.ws.jws1.Discoverer();
2450 // register PCS handler for desktop.
2451 discoverer.addPropertyChangeListener(changeSupport);
2453 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2454 // until we phase out completely
2455 (t0 = new Thread(discoverer)).start();
2458 // ENFIN services are EOLed as of Jalview 2.8.1 release
2463 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2465 // EnfinEnvision web service menu entries are rebuild every time the
2466 // menu is shown, so no changeSupport events are needed.
2467 jalview.ws.EnfinEnvision2OneWay.getInstance();
2468 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2471 } catch (Exception e)
2474 .info("Exception when trying to launch Envision2 workflow discovery.",
2476 Cache.log.info(e.getStackTrace());
2480 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2482 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2484 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2486 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2492 // TODO: do rest service discovery
2501 } catch (Exception e)
2504 alive = (t1 != null && t1.isAlive())
2505 || (t2 != null && t2.isAlive())
2506 || (t3 != null && t3.isAlive())
2507 || (t0 != null && t0.isAlive());
2513 * called to check if the service discovery process completed successfully.
2517 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2519 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2521 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2522 .getErrorMessages();
2525 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2527 if (serviceChangedDialog == null)
2529 // only run if we aren't already displaying one of these.
2530 addDialogThread(serviceChangedDialog = new Runnable()
2536 * JalviewDialog jd =new JalviewDialog() {
2538 * @Override protected void cancelPressed() { // TODO
2539 * Auto-generated method stub
2541 * }@Override protected void okPressed() { // TODO
2542 * Auto-generated method stub
2544 * }@Override protected void raiseClosed() { // TODO
2545 * Auto-generated method stub
2547 * } }; jd.initDialogFrame(new
2548 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2549 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2550 * + " or mis-configured HTTP proxy settings.<br/>" +
2551 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2553 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2554 * ), true, true, "Web Service Configuration Problem", 450,
2557 * jd.waitForInput();
2563 "<html><table width=\"450\"><tr><td>"
2565 + "</td></tr></table>"
2566 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2567 + " or mis-configured HTTP proxy settings.</p>"
2568 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2569 + " Tools->Preferences dialog box to change them.</p></html>"),
2570 "Web Service Configuration Problem",
2571 JOptionPane.DEFAULT_OPTION,
2572 JOptionPane.ERROR_MESSAGE);
2573 serviceChangedDialog = null;
2582 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2589 private Runnable serviceChangedDialog = null;
2592 * start a thread to open a URL in the configured browser. Pops up a warning
2593 * dialog to the user if there is an exception when calling out to the browser
2598 public static void showUrl(final String url)
2600 showUrl(url, Desktop.instance);
2604 * Like showUrl but allows progress handler to be specified
2608 * (null) or object implementing IProgressIndicator
2610 public static void showUrl(final String url,
2611 final IProgressIndicator progress)
2613 new Thread(new Runnable()
2619 if (progress != null)
2621 progress.setProgressBar("Opening " + url, this.hashCode());
2623 jalview.util.BrowserLauncher.openURL(url);
2624 } catch (Exception ex)
2627 .showInternalMessageDialog(
2629 "Unixers: Couldn't find default web browser."
2630 + "\nAdd the full path to your browser in Preferences.",
2631 "Web browser not found",
2632 JOptionPane.WARNING_MESSAGE);
2634 ex.printStackTrace();
2636 if (progress != null)
2638 progress.setProgressBar(null, this.hashCode());
2644 public static WsParamSetManager wsparamManager = null;
2646 public static ParamManager getUserParameterStore()
2648 if (wsparamManager == null)
2650 wsparamManager = new WsParamSetManager();
2652 return wsparamManager;
2656 * static hyperlink handler proxy method for use by Jalview's internal windows
2660 public static void hyperlinkUpdate(HyperlinkEvent e)
2662 if (e.getEventType() == EventType.ACTIVATED)
2667 url = e.getURL().toString();
2668 Desktop.showUrl(url);
2669 } catch (Exception x)
2673 if (Cache.log != null)
2675 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2679 System.err.println("Couldn't handle string " + url
2683 // ignore any exceptions due to dud links.
2690 * single thread that handles display of dialogs to user.
2692 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2695 * flag indicating if dialogExecutor should try to acquire a permit
2697 private volatile boolean dialogPause = true;
2702 private java.util.concurrent.Semaphore block = new Semaphore(0);
2705 * add another dialog thread to the queue
2709 public void addDialogThread(final Runnable prompter)
2711 dialogExecutor.submit(new Runnable()
2720 } catch (InterruptedException x)
2725 if (instance == null)
2731 SwingUtilities.invokeAndWait(prompter);
2732 } catch (Exception q)
2734 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2740 public void startDialogQueue()
2742 // set the flag so we don't pause waiting for another permit and semaphore
2743 // the current task to begin
2744 dialogPause = false;