2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.bin.Cache;
24 import jalview.io.FileLoader;
25 import jalview.io.FormatAdapter;
26 import jalview.io.IdentifyFile;
27 import jalview.io.JalviewFileChooser;
28 import jalview.io.JalviewFileView;
29 import jalview.util.ImageMaker;
30 import jalview.util.MessageManager;
31 import jalview.ws.params.ParamManager;
33 import java.awt.BorderLayout;
34 import java.awt.Color;
35 import java.awt.Dimension;
36 import java.awt.FontMetrics;
37 import java.awt.Graphics;
38 import java.awt.GridLayout;
39 import java.awt.Point;
40 import java.awt.Rectangle;
41 import java.awt.Toolkit;
42 import java.awt.datatransfer.Clipboard;
43 import java.awt.datatransfer.ClipboardOwner;
44 import java.awt.datatransfer.DataFlavor;
45 import java.awt.datatransfer.Transferable;
46 import java.awt.dnd.DnDConstants;
47 import java.awt.dnd.DropTargetDragEvent;
48 import java.awt.dnd.DropTargetDropEvent;
49 import java.awt.dnd.DropTargetEvent;
50 import java.awt.dnd.DropTargetListener;
51 import java.awt.event.ActionEvent;
52 import java.awt.event.ActionListener;
53 import java.awt.event.FocusEvent;
54 import java.awt.event.FocusListener;
55 import java.awt.event.MouseAdapter;
56 import java.awt.event.MouseEvent;
57 import java.awt.event.MouseListener;
58 import java.awt.event.WindowAdapter;
59 import java.awt.event.WindowEvent;
60 import java.beans.PropertyChangeEvent;
61 import java.beans.PropertyChangeListener;
62 import java.beans.PropertyVetoException;
63 import java.io.BufferedInputStream;
65 import java.io.FileOutputStream;
66 import java.lang.reflect.Constructor;
68 import java.util.ArrayList;
69 import java.util.Hashtable;
70 import java.util.StringTokenizer;
71 import java.util.Vector;
72 import java.util.concurrent.ExecutorService;
73 import java.util.concurrent.Executors;
74 import java.util.concurrent.Semaphore;
76 import javax.swing.DefaultDesktopManager;
77 import javax.swing.DesktopManager;
78 import javax.swing.JButton;
79 import javax.swing.JComboBox;
80 import javax.swing.JComponent;
81 import javax.swing.JDesktopPane;
82 import javax.swing.JFrame;
83 import javax.swing.JInternalFrame;
84 import javax.swing.JLabel;
85 import javax.swing.JMenuItem;
86 import javax.swing.JOptionPane;
87 import javax.swing.JPanel;
88 import javax.swing.JPopupMenu;
89 import javax.swing.JProgressBar;
90 import javax.swing.SwingUtilities;
91 import javax.swing.event.HyperlinkEvent;
92 import javax.swing.event.MenuEvent;
93 import javax.swing.event.MenuListener;
94 import javax.swing.event.HyperlinkEvent.EventType;
101 * @version $Revision: 1.155 $
103 public class Desktop extends jalview.jbgui.GDesktop implements
104 DropTargetListener, ClipboardOwner, IProgressIndicator,
105 jalview.api.StructureSelectionManagerProvider
108 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
111 * news reader - null if it was never started.
113 private BlogReader jvnews = null;
117 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
119 public void addJalviewPropertyChangeListener(
120 PropertyChangeListener listener)
122 changeSupport.addJalviewPropertyChangeListener(listener);
126 * @param propertyName
128 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
129 * java.beans.PropertyChangeListener)
131 public void addJalviewPropertyChangeListener(String propertyName,
132 PropertyChangeListener listener)
134 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
138 * @param propertyName
140 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
141 * java.beans.PropertyChangeListener)
143 public void removeJalviewPropertyChangeListener(String propertyName,
144 PropertyChangeListener listener)
146 changeSupport.removeJalviewPropertyChangeListener(propertyName,
150 /** Singleton Desktop instance */
151 public static Desktop instance;
153 public static MyDesktopPane desktop;
155 static int openFrameCount = 0;
157 static final int xOffset = 30;
159 static final int yOffset = 30;
161 public static jalview.ws.jws1.Discoverer discoverer;
163 public static Object[] jalviewClipboard;
165 public static boolean internalCopy = false;
167 static int fileLoadingCount = 0;
169 class MyDesktopManager implements DesktopManager
172 private DesktopManager delegate;
174 public MyDesktopManager(DesktopManager delegate)
176 this.delegate = delegate;
179 public void activateFrame(JInternalFrame f)
183 delegate.activateFrame(f);
184 } catch (NullPointerException npe)
186 Point p = getMousePosition();
187 instance.showPasteMenu(p.x, p.y);
191 public void beginDraggingFrame(JComponent f)
193 delegate.beginDraggingFrame(f);
196 public void beginResizingFrame(JComponent f, int direction)
198 delegate.beginResizingFrame(f, direction);
201 public void closeFrame(JInternalFrame f)
203 delegate.closeFrame(f);
206 public void deactivateFrame(JInternalFrame f)
208 delegate.deactivateFrame(f);
211 public void deiconifyFrame(JInternalFrame f)
213 delegate.deiconifyFrame(f);
216 public void dragFrame(JComponent f, int newX, int newY)
222 delegate.dragFrame(f, newX, newY);
225 public void endDraggingFrame(JComponent f)
227 delegate.endDraggingFrame(f);
230 public void endResizingFrame(JComponent f)
232 delegate.endResizingFrame(f);
235 public void iconifyFrame(JInternalFrame f)
237 delegate.iconifyFrame(f);
240 public void maximizeFrame(JInternalFrame f)
242 delegate.maximizeFrame(f);
245 public void minimizeFrame(JInternalFrame f)
247 delegate.minimizeFrame(f);
250 public void openFrame(JInternalFrame f)
252 delegate.openFrame(f);
255 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
258 Rectangle b = desktop.getBounds();
263 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
266 public void setBoundsForFrame(JComponent f, int newX, int newY,
267 int newWidth, int newHeight)
269 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
272 // All other methods, simply delegate
277 * Creates a new Desktop object.
282 * A note to implementors. It is ESSENTIAL that any activities that might
283 * block are spawned off as threads rather than waited for during this
287 doVamsasClientCheck();
290 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
291 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
292 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
294 boolean showjconsole = jalview.bin.Cache.getDefault(
295 "SHOW_JAVA_CONSOLE", false);
296 desktop = new MyDesktopPane(selmemusage);
297 showMemusage.setSelected(selmemusage);
298 desktop.setBackground(Color.white);
299 getContentPane().setLayout(new BorderLayout());
300 // alternate config - have scrollbars - see notes in JAL-153
301 // JScrollPane sp = new JScrollPane();
302 // sp.getViewport().setView(desktop);
303 // getContentPane().add(sp, BorderLayout.CENTER);
304 getContentPane().add(desktop, BorderLayout.CENTER);
305 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
307 // This line prevents Windows Look&Feel resizing all new windows to maximum
308 // if previous window was maximised
309 desktop.setDesktopManager(new MyDesktopManager(
310 new DefaultDesktopManager()));
312 Rectangle dims = getLastKnownDimensions("");
319 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
320 setBounds((int) (screenSize.width - 900) / 2,
321 (int) (screenSize.height - 650) / 2, 900, 650);
323 jconsole = new Console(this, showjconsole);
324 // add essential build information
325 jconsole.setHeader("Jalview Desktop "
326 + jalview.bin.Cache.getProperty("VERSION") + "\n"
328 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
329 + "Java version: " + System.getProperty("java.version") + "\n"
330 + System.getProperty("os.arch") + " "
331 + System.getProperty("os.name") + " "
332 + System.getProperty("os.version"));
334 showConsole(showjconsole);
336 showNews.setVisible(false);
338 this.addWindowListener(new WindowAdapter()
340 public void windowClosing(WindowEvent evt)
347 this.addMouseListener(ma = new MouseAdapter()
349 public void mousePressed(MouseEvent evt)
351 if (SwingUtilities.isRightMouseButton(evt))
353 showPasteMenu(evt.getX(), evt.getY());
357 desktop.addMouseListener(ma);
359 this.addFocusListener(new FocusListener()
363 public void focusLost(FocusEvent e)
365 // TODO Auto-generated method stub
370 public void focusGained(FocusEvent e)
372 Cache.log.debug("Relaying windows after focus gain");
373 // make sure that we sort windows properly after we gain focus
374 instance.relayerWindows();
377 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
378 // Spawn a thread that shows the splashscreen
379 SwingUtilities.invokeLater(new Runnable()
388 // Thread off a new instance of the file chooser - this reduces the time it
389 // takes to open it later on.
390 new Thread(new Runnable()
394 Cache.log.debug("Filechooser init thread started.");
395 JalviewFileChooser chooser = new JalviewFileChooser(
396 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
397 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
398 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
399 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
400 Cache.log.debug("Filechooser init thread finished.");
403 // Add the service change listener
404 changeSupport.addJalviewPropertyChangeListener("services",
405 new PropertyChangeListener()
409 public void propertyChange(PropertyChangeEvent evt)
411 Cache.log.debug("Firing service changed event for "
412 + evt.getNewValue());
413 JalviewServicesChanged(evt);
419 public void checkForNews()
421 final Desktop me = this;
422 // Thread off the news reader, in case there are connection problems.
423 addDialogThread(new Runnable()
428 Cache.log.debug("Starting news thread.");
430 jvnews = new BlogReader(me);
431 showNews.setVisible(true);
432 Cache.log.debug("Completed news thread.");
437 protected void showNews_actionPerformed(ActionEvent e)
439 showNews(showNews.isSelected());
442 void showNews(boolean visible)
445 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
446 showNews.setSelected(visible);
447 if (visible && !jvnews.isVisible())
449 new Thread(new Runnable()
454 long instance = System.currentTimeMillis();
455 Desktop.instance.setProgressBar(MessageManager.getString("status.refreshing_news"), instance);
456 jvnews.refreshNews();
457 Desktop.instance.setProgressBar(null, instance);
466 * recover the last known dimensions for a jalview window
469 * - empty string is desktop, all other windows have unique prefix
470 * @return null or last known dimensions scaled to current geometry (if last
471 * window geom was known)
473 Rectangle getLastKnownDimensions(String windowName)
475 // TODO: lock aspect ratio for scaling desktop Bug #0058199
476 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
477 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
478 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
479 String width = jalview.bin.Cache.getProperty(windowName
481 String height = jalview.bin.Cache.getProperty(windowName
483 if ((x != null) && (y != null) && (width != null) && (height != null))
485 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
486 .parseInt(width), ih = Integer.parseInt(height);
487 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
489 // attempt #1 - try to cope with change in screen geometry - this
490 // version doesn't preserve original jv aspect ratio.
491 // take ratio of current screen size vs original screen size.
492 double sw = ((1f * screenSize.width) / (1f * Integer
493 .parseInt(jalview.bin.Cache
494 .getProperty("SCREENGEOMETRY_WIDTH"))));
495 double sh = ((1f * screenSize.height) / (1f * Integer
496 .parseInt(jalview.bin.Cache
497 .getProperty("SCREENGEOMETRY_HEIGHT"))));
498 // rescale the bounds depending upon the current screen geometry.
499 ix = (int) (ix * sw);
500 iw = (int) (iw * sw);
501 iy = (int) (iy * sh);
502 ih = (int) (ih * sh);
503 while (ix >= screenSize.width)
505 jalview.bin.Cache.log
506 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
507 ix -= screenSize.width;
509 while (iy >= screenSize.height)
511 jalview.bin.Cache.log
512 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
513 iy -= screenSize.height;
515 jalview.bin.Cache.log.debug("Got last known dimensions for "
516 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
519 // return dimensions for new instance
520 return new Rectangle(ix, iy, iw, ih);
525 private void doVamsasClientCheck()
527 if (jalview.bin.Cache.vamsasJarsPresent())
529 setupVamsasDisconnectedGui();
530 VamsasMenu.setVisible(true);
531 final Desktop us = this;
532 VamsasMenu.addMenuListener(new MenuListener()
534 // this listener remembers when the menu was first selected, and
535 // doesn't rebuild the session list until it has been cleared and
537 boolean refresh = true;
539 public void menuCanceled(MenuEvent e)
544 public void menuDeselected(MenuEvent e)
549 public void menuSelected(MenuEvent e)
553 us.buildVamsasStMenu();
558 vamsasStart.setVisible(true);
562 void showPasteMenu(int x, int y)
564 JPopupMenu popup = new JPopupMenu();
565 JMenuItem item = new JMenuItem(
566 MessageManager.getString("label.paste_new_window"));
567 item.addActionListener(new ActionListener()
569 public void actionPerformed(ActionEvent evt)
576 popup.show(this, x, y);
583 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
584 Transferable contents = c.getContents(this);
586 if (contents != null)
588 String file = (String) contents
589 .getTransferData(DataFlavor.stringFlavor);
591 String format = new IdentifyFile().Identify(file,
592 FormatAdapter.PASTE);
594 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
597 } catch (Exception ex)
600 .println("Unable to paste alignment from system clipboard:\n"
606 * Adds and opens the given frame to the desktop
617 public static synchronized void addInternalFrame(
618 final JInternalFrame frame, String title, int w, int h)
620 addInternalFrame(frame, title, w, h, true);
637 public static synchronized void addInternalFrame(
638 final JInternalFrame frame, String title, int w, int h,
642 // TODO: allow callers to determine X and Y position of frame (eg. via
644 // TODO: consider fixing method to update entries in the window submenu with
645 // the current window title
647 frame.setTitle(title);
648 if (frame.getWidth() < 1 || frame.getHeight() < 1)
652 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
653 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
654 // IF JALVIEW IS RUNNING HEADLESS
655 // ///////////////////////////////////////////////
657 || (System.getProperty("java.awt.headless") != null && System
658 .getProperty("java.awt.headless").equals("true")))
665 frame.setVisible(true);
666 frame.setClosable(true);
667 frame.setResizable(resizable);
668 frame.setMaximizable(resizable);
669 frame.setIconifiable(resizable);
670 frame.setFrameIcon(null);
672 if (frame.getX() < 1 && frame.getY() < 1)
674 frame.setLocation(xOffset * openFrameCount, yOffset
675 * ((openFrameCount - 1) % 10) + yOffset);
678 final JMenuItem menuItem = new JMenuItem(title);
679 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
681 public void internalFrameActivated(
682 javax.swing.event.InternalFrameEvent evt)
684 JInternalFrame itf = desktop.getSelectedFrame();
692 public void internalFrameClosed(
693 javax.swing.event.InternalFrameEvent evt)
695 PaintRefresher.RemoveComponent(frame);
697 windowMenu.remove(menuItem);
698 JInternalFrame itf = desktop.getSelectedFrame();
707 menuItem.addActionListener(new ActionListener()
709 public void actionPerformed(ActionEvent e)
713 frame.setSelected(true);
714 frame.setIcon(false);
715 } catch (java.beans.PropertyVetoException ex)
721 menuItem.addMouseListener(new MouseListener()
725 public void mouseReleased(MouseEvent e)
730 public void mousePressed(MouseEvent e)
735 public void mouseExited(MouseEvent e)
739 frame.setSelected(false);
740 } catch (PropertyVetoException e1)
746 public void mouseEntered(MouseEvent e)
750 frame.setSelected(true);
751 } catch (PropertyVetoException e1)
757 public void mouseClicked(MouseEvent e)
763 windowMenu.add(menuItem);
769 frame.setSelected(true);
770 frame.requestFocus();
771 } catch (java.beans.PropertyVetoException ve)
773 } catch (java.lang.ClassCastException cex)
776 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
781 public void lostOwnership(Clipboard clipboard, Transferable contents)
785 Desktop.jalviewClipboard = null;
788 internalCopy = false;
791 public void dragEnter(DropTargetDragEvent evt)
795 public void dragExit(DropTargetEvent evt)
799 public void dragOver(DropTargetDragEvent evt)
803 public void dropActionChanged(DropTargetDragEvent evt)
813 public void drop(DropTargetDropEvent evt)
815 boolean success = true;
816 Transferable t = evt.getTransferable();
817 java.util.List files = null;
818 java.util.List protocols = null;
822 DataFlavor uriListFlavor = new DataFlavor(
823 "text/uri-list;class=java.lang.String");
824 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
826 // Works on Windows and MacOSX
827 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
828 files = (java.util.List) t
829 .getTransferData(DataFlavor.javaFileListFlavor);
831 else if (t.isDataFlavorSupported(uriListFlavor))
833 // This is used by Unix drag system
834 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
835 String data = (String) t.getTransferData(uriListFlavor);
836 files = new java.util.ArrayList(1);
837 protocols = new java.util.ArrayList(1);
838 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
839 data, "\r\n"); st.hasMoreTokens();)
841 String s = st.nextToken();
842 if (s.startsWith("#"))
844 // the line is a comment (as per the RFC 2483)
847 java.net.URI uri = new java.net.URI(s);
848 if (uri.getScheme().toLowerCase().startsWith("http"))
850 protocols.add(FormatAdapter.URL);
851 files.add(uri.toString());
855 // otherwise preserve old behaviour: catch all for file objects
856 java.io.File file = new java.io.File(uri);
857 protocols.add(FormatAdapter.FILE);
858 files.add(file.toString());
862 } catch (Exception e)
871 for (int i = 0; i < files.size(); i++)
873 String file = files.get(i).toString();
874 String protocol = (protocols == null) ? FormatAdapter.FILE
875 : (String) protocols.get(i);
876 String format = null;
878 if (file.endsWith(".jar"))
885 format = new IdentifyFile().Identify(file, protocol);
888 new FileLoader().LoadFile(file, protocol, format);
891 } catch (Exception ex)
896 evt.dropComplete(success); // need this to ensure input focus is properly
897 // transfered to any new windows created
906 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
908 JalviewFileChooser chooser = new JalviewFileChooser(
909 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
910 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
911 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
912 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
914 chooser.setFileView(new JalviewFileView());
915 chooser.setDialogTitle(MessageManager
916 .getString("label.open_local_file"));
917 chooser.setToolTipText(MessageManager.getString("action.open"));
919 int value = chooser.showOpenDialog(this);
921 if (value == JalviewFileChooser.APPROVE_OPTION)
923 String choice = chooser.getSelectedFile().getPath();
924 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
925 .getSelectedFile().getParent());
927 String format = null;
928 if (chooser.getSelectedFormat() != null
929 && chooser.getSelectedFormat().equals("Jalview"))
935 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
938 if (viewport != null)
940 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
945 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
956 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
958 // This construct allows us to have a wider textfield
960 JLabel label = new JLabel(
961 MessageManager.getString("label.input_file_url"));
962 final JComboBox history = new JComboBox();
964 JPanel panel = new JPanel(new GridLayout(2, 1));
967 history.setPreferredSize(new Dimension(400, 20));
968 history.setEditable(true);
969 history.addItem("http://www.");
971 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
975 if (historyItems != null)
977 st = new StringTokenizer(historyItems, "\t");
979 while (st.hasMoreTokens())
981 history.addItem(st.nextElement());
985 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
986 MessageManager.getString("label.input_alignment_from_url"),
987 JOptionPane.OK_CANCEL_OPTION);
989 if (reply != JOptionPane.OK_OPTION)
994 String url = history.getSelectedItem().toString();
996 if (url.toLowerCase().endsWith(".jar"))
998 if (viewport != null)
1000 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1005 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1010 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1012 if (format.equals("URL NOT FOUND"))
1014 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1015 MessageManager.formatMessage("label.couldnt_locate", new String[]{url}), MessageManager.getString("label.url_not_found"),
1016 JOptionPane.WARNING_MESSAGE);
1021 if (viewport != null)
1023 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1027 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1038 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1040 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1041 cap.setForInput(viewport);
1042 Desktop.addInternalFrame(cap, MessageManager.getString("label.cut_paste_alignmen_file"), 600, 500);
1050 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1052 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1053 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1055 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1056 getBounds().y, getWidth(), getHeight()));
1058 if (jconsole != null)
1060 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1061 jconsole.stopConsole();
1065 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1068 if (dialogExecutor != null)
1070 dialogExecutor.shutdownNow();
1076 private void storeLastKnownDimensions(String string, Rectangle jc)
1078 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1079 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1080 + " height:" + jc.height);
1082 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1083 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1084 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1085 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1094 public void aboutMenuItem_actionPerformed(ActionEvent e)
1096 // StringBuffer message = getAboutMessage(false);
1097 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1099 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1100 new Thread(new Runnable()
1104 new SplashScreen(true);
1109 public StringBuffer getAboutMessage(boolean shortv)
1111 StringBuffer message = new StringBuffer();
1112 message.append("<html>");
1115 message.append("<h1><strong>Version: "
1116 + jalview.bin.Cache.getProperty("VERSION")
1117 + "</strong></h1>");
1118 message.append("<strong>Last Updated: <em>"
1119 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1120 + "</em></strong>");
1126 message.append("<strong>Version "
1127 + jalview.bin.Cache.getProperty("VERSION")
1128 + "; last updated: "
1129 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1132 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1135 message.append("<br>...Checking latest version...</br>");
1137 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1138 .equals(jalview.bin.Cache.getProperty("VERSION")))
1140 boolean red = false;
1141 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1142 .indexOf("automated build") == -1)
1145 // Displayed when code version and jnlp version do not match and code
1146 // version is not a development build
1147 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1150 message.append("<br>!! Version "
1151 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1153 + " is available for download from "
1154 + jalview.bin.Cache.getDefault("www.jalview.org",
1155 "http://www.jalview.org") + " !!");
1158 message.append("</div>");
1161 message.append("<br>Authors: "
1165 "The Jalview Authors (See AUTHORS file for current list)")
1166 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1167 + "<br><br>For help, see the FAQ at <a href=\"http://www.jalview.org/faq\">www.jalview.org/faq</a> and/or join the jalview-discuss@jalview.org mailing list"
1168 + "<br><br>If you use Jalview, please cite:"
1169 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1170 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1171 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1182 public void documentationMenuItem_actionPerformed(ActionEvent e)
1186 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
1187 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
1188 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
1190 javax.help.HelpBroker hb = hs.createHelpBroker();
1191 hb.setCurrentID("home");
1192 hb.setDisplayed(true);
1193 } catch (Exception ex)
1198 public void closeAll_actionPerformed(ActionEvent e)
1200 JInternalFrame[] frames = desktop.getAllFrames();
1201 for (int i = 0; i < frames.length; i++)
1205 frames[i].setClosed(true);
1206 } catch (java.beans.PropertyVetoException ex)
1210 System.out.println("ALL CLOSED");
1211 if (v_client != null)
1213 // TODO clear binding to vamsas document objects on close_all
1218 public void raiseRelated_actionPerformed(ActionEvent e)
1220 reorderAssociatedWindows(false, false);
1223 public void minimizeAssociated_actionPerformed(ActionEvent e)
1225 reorderAssociatedWindows(true, false);
1228 void closeAssociatedWindows()
1230 reorderAssociatedWindows(false, true);
1236 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1239 protected void garbageCollect_actionPerformed(ActionEvent e)
1241 // We simply collect the garbage
1242 jalview.bin.Cache.log.debug("Collecting garbage...");
1244 jalview.bin.Cache.log.debug("Finished garbage collection.");
1251 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1254 protected void showMemusage_actionPerformed(ActionEvent e)
1256 desktop.showMemoryUsage(showMemusage.isSelected());
1263 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1266 protected void showConsole_actionPerformed(ActionEvent e)
1268 showConsole(showConsole.isSelected());
1271 Console jconsole = null;
1274 * control whether the java console is visible or not
1278 void showConsole(boolean selected)
1280 showConsole.setSelected(selected);
1281 // TODO: decide if we should update properties file
1282 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1284 jconsole.setVisible(selected);
1287 void reorderAssociatedWindows(boolean minimize, boolean close)
1289 JInternalFrame[] frames = desktop.getAllFrames();
1290 if (frames == null || frames.length < 1)
1295 AlignViewport source = null, target = null;
1296 if (frames[0] instanceof AlignFrame)
1298 source = ((AlignFrame) frames[0]).getCurrentView();
1300 else if (frames[0] instanceof TreePanel)
1302 source = ((TreePanel) frames[0]).getViewPort();
1304 else if (frames[0] instanceof PCAPanel)
1306 source = ((PCAPanel) frames[0]).av;
1308 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1310 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1315 for (int i = 0; i < frames.length; i++)
1318 if (frames[i] == null)
1322 if (frames[i] instanceof AlignFrame)
1324 target = ((AlignFrame) frames[i]).getCurrentView();
1326 else if (frames[i] instanceof TreePanel)
1328 target = ((TreePanel) frames[i]).getViewPort();
1330 else if (frames[i] instanceof PCAPanel)
1332 target = ((PCAPanel) frames[i]).av;
1334 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1336 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1339 if (source == target)
1345 frames[i].setClosed(true);
1349 frames[i].setIcon(minimize);
1352 frames[i].toFront();
1356 } catch (java.beans.PropertyVetoException ex)
1370 protected void preferences_actionPerformed(ActionEvent e)
1381 public void saveState_actionPerformed(ActionEvent e)
1383 JalviewFileChooser chooser = new JalviewFileChooser(
1384 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1385 { "jvp" }, new String[]
1386 { "Jalview Project" }, "Jalview Project");
1388 chooser.setFileView(new JalviewFileView());
1389 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1391 int value = chooser.showSaveDialog(this);
1393 if (value == JalviewFileChooser.APPROVE_OPTION)
1395 final Desktop me = this;
1396 final java.io.File choice = chooser.getSelectedFile();
1397 new Thread(new Runnable()
1402 setProgressBar(MessageManager.formatMessage("label.saving_jalview_project", new String[]{choice.getName()}),
1404 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1405 choice.getParent());
1406 // TODO catch and handle errors for savestate
1407 // TODO prevent user from messing with the Desktop whilst we're saving
1410 new Jalview2XML().SaveState(choice);
1411 } catch (OutOfMemoryError oom)
1413 new OOMWarning("Whilst saving current state to "
1414 + choice.getName(), oom);
1415 } catch (Exception ex)
1418 "Problems whilst trying to save to " + choice.getName(),
1420 JOptionPane.showMessageDialog(
1422 MessageManager.formatMessage("label.error_whilst_saving_current_state_to", new String[]{ choice.getName()}),
1423 MessageManager.getString("label.couldnt_save_project"),
1424 JOptionPane.WARNING_MESSAGE);
1426 setProgressBar(null, choice.hashCode());
1438 public void loadState_actionPerformed(ActionEvent e)
1440 JalviewFileChooser chooser = new JalviewFileChooser(
1441 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1442 { "jvp", "jar" }, new String[]
1443 { "Jalview Project", "Jalview Project (old)" },
1445 chooser.setFileView(new JalviewFileView());
1446 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1448 int value = chooser.showOpenDialog(this);
1450 if (value == JalviewFileChooser.APPROVE_OPTION)
1452 final String choice = chooser.getSelectedFile().getAbsolutePath();
1453 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1454 .getSelectedFile().getParent());
1455 new Thread(new Runnable()
1459 setProgressBar(MessageManager.formatMessage("label.loading_jalview_project", new String[]{choice}),
1463 new Jalview2XML().LoadJalviewAlign(choice);
1464 } catch (OutOfMemoryError oom)
1466 new OOMWarning("Whilst loading project from " + choice, oom);
1467 } catch (Exception ex)
1469 Cache.log.error("Problems whilst loading project from "
1471 JOptionPane.showMessageDialog(Desktop.desktop,
1472 MessageManager.formatMessage("label.error_whilst_loading_project_from", new String[]{choice}),
1473 MessageManager.getString("label.couldnt_load_project"), JOptionPane.WARNING_MESSAGE);
1475 setProgressBar(null, choice.hashCode());
1481 public void inputSequence_actionPerformed(ActionEvent e)
1483 new SequenceFetcher(this);
1486 JPanel progressPanel;
1488 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1490 public void startLoading(final String fileName)
1492 if (fileLoadingCount == 0)
1494 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage("label.loading_file", new String[]{fileName})));
1499 private JPanel addProgressPanel(String string)
1501 if (progressPanel == null)
1503 progressPanel = new JPanel(new GridLayout(1, 1));
1504 totalProgressCount = 0;
1505 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1507 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1508 JProgressBar progressBar = new JProgressBar();
1509 progressBar.setIndeterminate(true);
1511 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1513 thisprogress.add(progressBar, BorderLayout.CENTER);
1514 progressPanel.add(thisprogress);
1515 ((GridLayout) progressPanel.getLayout())
1516 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1517 ++totalProgressCount;
1518 instance.validate();
1519 return thisprogress;
1522 int totalProgressCount = 0;
1524 private void removeProgressPanel(JPanel progbar)
1526 if (progressPanel != null)
1528 synchronized (progressPanel)
1530 progressPanel.remove(progbar);
1531 GridLayout gl = (GridLayout) progressPanel.getLayout();
1532 gl.setRows(gl.getRows() - 1);
1533 if (--totalProgressCount < 1)
1535 this.getContentPane().remove(progressPanel);
1536 progressPanel = null;
1543 public void stopLoading()
1546 if (fileLoadingCount < 1)
1548 while (fileLoadingPanels.size() > 0)
1550 removeProgressPanel(fileLoadingPanels.remove(0));
1552 fileLoadingPanels.clear();
1553 fileLoadingCount = 0;
1558 public static int getViewCount(String alignmentId)
1560 AlignViewport[] aps = getViewports(alignmentId);
1561 return (aps == null) ? 0 : aps.length;
1566 * @param alignmentId
1567 * @return all AlignmentPanels concerning the alignmentId sequence set
1569 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1572 if (Desktop.desktop == null)
1574 // no frames created and in headless mode
1575 // TODO: verify that frames are recoverable when in headless mode
1578 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1579 ArrayList aps = new ArrayList();
1580 for (int t = 0; t < frames.length; t++)
1582 if (frames[t] instanceof AlignFrame)
1584 AlignFrame af = (AlignFrame) frames[t];
1585 for (int a = 0; a < af.alignPanels.size(); a++)
1587 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1588 .elementAt(a)).av.getSequenceSetId()))
1590 aps.add(af.alignPanels.elementAt(a));
1595 if (aps.size() == 0)
1599 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1600 for (int t = 0; t < vap.length; t++)
1602 vap[t] = (AlignmentPanel) aps.get(t);
1608 * get all the viewports on an alignment.
1610 * @param sequenceSetId
1611 * unique alignment id
1612 * @return all viewports on the alignment bound to sequenceSetId
1614 public static AlignViewport[] getViewports(String sequenceSetId)
1616 Vector viewp = new Vector();
1617 if (desktop != null)
1619 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1621 for (int t = 0; t < frames.length; t++)
1623 if (frames[t] instanceof AlignFrame)
1625 AlignFrame afr = ((AlignFrame) frames[t]);
1626 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1628 if (afr.alignPanels != null)
1630 for (int a = 0; a < afr.alignPanels.size(); a++)
1632 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1633 .elementAt(a)).av.getSequenceSetId()))
1635 viewp.addElement(((AlignmentPanel) afr.alignPanels
1642 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1647 if (viewp.size() > 0)
1649 AlignViewport[] vp = new AlignViewport[viewp.size()];
1657 public void explodeViews(AlignFrame af)
1659 int size = af.alignPanels.size();
1665 for (int i = 0; i < size; i++)
1667 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1668 AlignFrame newaf = new AlignFrame(ap);
1669 if (ap.av.explodedPosition != null
1670 && !ap.av.explodedPosition.equals(af.getBounds()))
1672 newaf.setBounds(ap.av.explodedPosition);
1675 ap.av.gatherViewsHere = false;
1677 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1678 AlignFrame.DEFAULT_HEIGHT);
1681 af.alignPanels.clear();
1682 af.closeMenuItem_actionPerformed(true);
1686 public void gatherViews(AlignFrame source)
1688 source.viewport.gatherViewsHere = true;
1689 source.viewport.explodedPosition = source.getBounds();
1690 JInternalFrame[] frames = desktop.getAllFrames();
1691 String viewId = source.viewport.getSequenceSetId();
1693 for (int t = 0; t < frames.length; t++)
1695 if (frames[t] instanceof AlignFrame && frames[t] != source)
1697 AlignFrame af = (AlignFrame) frames[t];
1698 boolean gatherThis = false;
1699 for (int a = 0; a < af.alignPanels.size(); a++)
1701 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1702 if (viewId.equals(ap.av.getSequenceSetId()))
1705 ap.av.gatherViewsHere = false;
1706 ap.av.explodedPosition = af.getBounds();
1707 source.addAlignmentPanel(ap, false);
1713 af.alignPanels.clear();
1714 af.closeMenuItem_actionPerformed(true);
1721 jalview.gui.VamsasApplication v_client = null;
1723 public void vamsasImport_actionPerformed(ActionEvent e)
1725 if (v_client == null)
1727 // Load and try to start a session.
1728 JalviewFileChooser chooser = new JalviewFileChooser(
1729 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1731 chooser.setFileView(new JalviewFileView());
1732 chooser.setDialogTitle(MessageManager.getString("label.open_saved_vamsas_session"));
1733 chooser.setToolTipText(MessageManager
1734 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1736 int value = chooser.showOpenDialog(this);
1738 if (value == JalviewFileChooser.APPROVE_OPTION)
1740 String fle = chooser.getSelectedFile().toString();
1741 if (!vamsasImport(chooser.getSelectedFile()))
1744 .showInternalMessageDialog(
1746 MessageManager.formatMessage(
1747 "label.couldnt_import_as_vamsas_session",
1751 .getString("label.vamsas_document_import_failed"),
1752 JOptionPane.ERROR_MESSAGE);
1758 jalview.bin.Cache.log
1759 .error("Implementation error - load session from a running session is not supported.");
1764 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1767 * @return true if import was a success and a session was started.
1769 public boolean vamsasImport(URL url)
1771 // TODO: create progress bar
1772 if (v_client != null)
1775 jalview.bin.Cache.log
1776 .error("Implementation error - load session from a running session is not supported.");
1782 // copy the URL content to a temporary local file
1783 // TODO: be a bit cleverer here with nio (?!)
1784 File file = File.createTempFile("vdocfromurl", ".vdj");
1785 FileOutputStream fos = new FileOutputStream(file);
1786 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1787 byte[] buffer = new byte[2048];
1789 while ((ln = bis.read(buffer)) > -1)
1791 fos.write(buffer, 0, ln);
1795 v_client = new jalview.gui.VamsasApplication(this, file,
1796 url.toExternalForm());
1797 } catch (Exception ex)
1799 jalview.bin.Cache.log.error(
1800 "Failed to create new vamsas session from contents of URL "
1804 setupVamsasConnectedGui();
1805 v_client.initial_update(); // TODO: thread ?
1806 return v_client.inSession();
1810 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1813 * @return true if import was a success and a session was started.
1815 public boolean vamsasImport(File file)
1817 if (v_client != null)
1820 jalview.bin.Cache.log
1821 .error("Implementation error - load session from a running session is not supported.");
1825 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1829 v_client = new jalview.gui.VamsasApplication(this, file, null);
1830 } catch (Exception ex)
1832 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1834 jalview.bin.Cache.log.error(
1835 "New vamsas session from existing session file failed:", ex);
1838 setupVamsasConnectedGui();
1839 v_client.initial_update(); // TODO: thread ?
1840 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1842 return v_client.inSession();
1845 public boolean joinVamsasSession(String mysesid)
1847 if (v_client != null)
1849 throw new Error(MessageManager.getString("error.try_join_vamsas_session_another"));
1851 if (mysesid == null)
1853 throw new Error(MessageManager.getString("error.invalid_vamsas_session_id"));
1855 v_client = new VamsasApplication(this, mysesid);
1856 setupVamsasConnectedGui();
1857 v_client.initial_update();
1858 return (v_client.inSession());
1861 public void vamsasStart_actionPerformed(ActionEvent e)
1863 if (v_client == null)
1866 // we just start a default session for moment.
1868 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1869 * getProperty("LAST_DIRECTORY"));
1871 * chooser.setFileView(new JalviewFileView());
1872 * chooser.setDialogTitle("Load Vamsas file");
1873 * chooser.setToolTipText("Import");
1875 * int value = chooser.showOpenDialog(this);
1877 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1878 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1880 v_client = new VamsasApplication(this);
1881 setupVamsasConnectedGui();
1882 v_client.initial_update(); // TODO: thread ?
1886 // store current data in session.
1887 v_client.push_update(); // TODO: thread
1891 protected void setupVamsasConnectedGui()
1893 vamsasStart.setText(MessageManager.getString("label.session_update"));
1894 vamsasSave.setVisible(true);
1895 vamsasStop.setVisible(true);
1896 vamsasImport.setVisible(false); // Document import to existing session is
1897 // not possible for vamsas-client-1.0.
1900 protected void setupVamsasDisconnectedGui()
1902 vamsasSave.setVisible(false);
1903 vamsasStop.setVisible(false);
1904 vamsasImport.setVisible(true);
1905 vamsasStart.setText(MessageManager
1906 .getString("label.new_vamsas_session"));
1909 public void vamsasStop_actionPerformed(ActionEvent e)
1911 if (v_client != null)
1913 v_client.end_session();
1915 setupVamsasDisconnectedGui();
1919 protected void buildVamsasStMenu()
1921 if (v_client == null)
1923 String[] sess = null;
1926 sess = VamsasApplication.getSessionList();
1927 } catch (Exception e)
1929 jalview.bin.Cache.log.warn(
1930 "Problem getting current sessions list.", e);
1935 jalview.bin.Cache.log.debug("Got current sessions list: "
1936 + sess.length + " entries.");
1937 VamsasStMenu.removeAll();
1938 for (int i = 0; i < sess.length; i++)
1940 JMenuItem sessit = new JMenuItem();
1941 sessit.setText(sess[i]);
1942 sessit.setToolTipText(MessageManager.formatMessage(
1943 "label.connect_to_session", new String[]
1945 final Desktop dsktp = this;
1946 final String mysesid = sess[i];
1947 sessit.addActionListener(new ActionListener()
1950 public void actionPerformed(ActionEvent e)
1952 if (dsktp.v_client == null)
1954 Thread rthr = new Thread(new Runnable()
1959 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1960 dsktp.setupVamsasConnectedGui();
1961 dsktp.v_client.initial_update();
1969 VamsasStMenu.add(sessit);
1971 // don't show an empty menu.
1972 VamsasStMenu.setVisible(sess.length > 0);
1977 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1978 VamsasStMenu.removeAll();
1979 VamsasStMenu.setVisible(false);
1984 // Not interested in the content. Just hide ourselves.
1985 VamsasStMenu.setVisible(false);
1989 public void vamsasSave_actionPerformed(ActionEvent e)
1991 if (v_client != null)
1993 JalviewFileChooser chooser = new JalviewFileChooser(
1994 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1995 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1997 { "Vamsas Document" }, "Vamsas Document");
1999 chooser.setFileView(new JalviewFileView());
2000 chooser.setDialogTitle(MessageManager.getString("label.save_vamsas_document_archive"));
2002 int value = chooser.showSaveDialog(this);
2004 if (value == JalviewFileChooser.APPROVE_OPTION)
2006 java.io.File choice = chooser.getSelectedFile();
2007 JPanel progpanel = addProgressPanel(MessageManager.formatMessage("label.saving_vamsas_doc", new String[]{choice.getName()}));
2008 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2009 String warnmsg = null;
2010 String warnttl = null;
2013 v_client.vclient.storeDocument(choice);
2016 warnttl = "Serious Problem saving Vamsas Document";
2017 warnmsg = ex.toString();
2018 jalview.bin.Cache.log.error("Error Whilst saving document to "
2021 } catch (Exception ex)
2023 warnttl = "Problem saving Vamsas Document.";
2024 warnmsg = ex.toString();
2025 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2029 removeProgressPanel(progpanel);
2030 if (warnmsg != null)
2032 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2034 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2040 JPanel vamUpdate = null;
2043 * hide vamsas user gui bits when a vamsas document event is being handled.
2046 * true to hide gui, false to reveal gui
2048 public void setVamsasUpdate(boolean b)
2050 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2051 + (b ? "in progress" : "finished"));
2053 if (vamUpdate != null)
2055 this.removeProgressPanel(vamUpdate);
2059 vamUpdate = this.addProgressPanel(MessageManager.getString("label.updating_vamsas_session"));
2061 vamsasStart.setVisible(!b);
2062 vamsasStop.setVisible(!b);
2063 vamsasSave.setVisible(!b);
2066 public JInternalFrame[] getAllFrames()
2068 return desktop.getAllFrames();
2072 * Checks the given url to see if it gives a response indicating that the user
2073 * should be informed of a new questionnaire.
2077 public void checkForQuestionnaire(String url)
2079 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2080 // javax.swing.SwingUtilities.invokeLater(jvq);
2081 new Thread(jvq).start();
2085 * Proxy class for JDesktopPane which optionally displays the current memory
2086 * usage and highlights the desktop area with a red bar if free memory runs
2091 public class MyDesktopPane extends JDesktopPane implements Runnable
2094 boolean showMemoryUsage = false;
2098 java.text.NumberFormat df;
2100 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2103 public MyDesktopPane(boolean showMemoryUsage)
2105 showMemoryUsage(showMemoryUsage);
2108 public void showMemoryUsage(boolean showMemoryUsage)
2110 this.showMemoryUsage = showMemoryUsage;
2111 if (showMemoryUsage)
2113 Thread worker = new Thread(this);
2118 public boolean isShowMemoryUsage()
2120 return showMemoryUsage;
2125 df = java.text.NumberFormat.getNumberInstance();
2126 df.setMaximumFractionDigits(2);
2127 runtime = Runtime.getRuntime();
2129 while (showMemoryUsage)
2133 maxMemory = runtime.maxMemory() / 1048576f;
2134 allocatedMemory = runtime.totalMemory() / 1048576f;
2135 freeMemory = runtime.freeMemory() / 1048576f;
2136 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2138 percentUsage = (totalFreeMemory / maxMemory) * 100;
2140 // if (percentUsage < 20)
2142 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2144 // instance.set.setBorder(border1);
2147 // sleep after showing usage
2149 } catch (Exception ex)
2151 ex.printStackTrace();
2156 public void paintComponent(Graphics g)
2158 if (showMemoryUsage && g != null && df != null)
2160 if (percentUsage < 20)
2161 g.setColor(Color.red);
2162 FontMetrics fm = g.getFontMetrics();
2165 g.drawString(MessageManager.formatMessage(
2166 "label.memory_stats",
2168 { df.format(totalFreeMemory), df.format(maxMemory),
2169 df.format(percentUsage) }), 10,
2170 getHeight() - fm.getHeight());
2177 * fixes stacking order after a modal dialog to ensure windows that should be
2178 * on top actually are
2180 public void relayerWindows()
2185 protected JMenuItem groovyShell;
2187 public void doGroovyCheck()
2189 if (jalview.bin.Cache.groovyJarsPresent())
2191 groovyShell = new JMenuItem();
2192 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2193 groovyShell.addActionListener(new ActionListener()
2195 public void actionPerformed(ActionEvent e)
2197 groovyShell_actionPerformed(e);
2200 toolsMenu.add(groovyShell);
2201 groovyShell.setVisible(true);
2206 * Accessor method to quickly get all the AlignmentFrames loaded.
2208 public static AlignFrame[] getAlignframes()
2210 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2216 Vector avp = new Vector();
2220 for (int i = frames.length - 1; i > -1; i--)
2222 if (frames[i] instanceof AlignFrame)
2224 AlignFrame af = (AlignFrame) frames[i];
2228 } catch (Exception ex)
2230 ex.printStackTrace();
2232 if (avp.size() == 0)
2236 AlignFrame afs[] = new AlignFrame[avp.size()];
2237 for (int i = 0, j = avp.size(); i < j; i++)
2239 afs[i] = (AlignFrame) avp.elementAt(i);
2245 public AppJmol[] getJmols()
2247 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2253 Vector avp = new Vector();
2257 for (int i = frames.length - 1; i > -1; i--)
2259 if (frames[i] instanceof AppJmol)
2261 AppJmol af = (AppJmol) frames[i];
2265 } catch (Exception ex)
2267 ex.printStackTrace();
2269 if (avp.size() == 0)
2273 AppJmol afs[] = new AppJmol[avp.size()];
2274 for (int i = 0, j = avp.size(); i < j; i++)
2276 afs[i] = (AppJmol) avp.elementAt(i);
2283 * Add Groovy Support to Jalview
2285 public void groovyShell_actionPerformed(ActionEvent e)
2287 // use reflection to avoid creating compilation dependency.
2288 if (!jalview.bin.Cache.groovyJarsPresent())
2290 throw new Error(MessageManager.getString("error.implementation_error_cannot_create_groovyshell"));
2294 Class gcClass = Desktop.class.getClassLoader().loadClass(
2295 "groovy.ui.Console");
2296 Constructor gccons = gcClass.getConstructor(null);
2297 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2299 { String.class, Object.class });
2300 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2301 Object gc = gccons.newInstance(null);
2302 setvar.invoke(gc, new Object[]
2303 { "Jalview", this });
2304 run.invoke(gc, null);
2305 } catch (Exception ex)
2307 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2309 .showInternalMessageDialog(
2312 MessageManager.getString("label.couldnt_create_groovy_shell"),
2313 MessageManager.getString("label.groovy_support_failed"),
2314 JOptionPane.ERROR_MESSAGE);
2319 * Progress bars managed by the IProgressIndicator method.
2321 private Hashtable<Long, JPanel> progressBars;
2323 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2328 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2330 public void setProgressBar(String message, long id)
2332 if (progressBars == null)
2334 progressBars = new Hashtable<Long, JPanel>();
2335 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2338 if (progressBars.get(new Long(id)) != null)
2340 JPanel progressPanel = progressBars.remove(new Long(id));
2341 if (progressBarHandlers.contains(new Long(id)))
2343 progressBarHandlers.remove(new Long(id));
2345 removeProgressPanel(progressPanel);
2349 progressBars.put(new Long(id), addProgressPanel(message));
2356 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2357 * jalview.gui.IProgressIndicatorHandler)
2359 public void registerHandler(final long id,
2360 final IProgressIndicatorHandler handler)
2362 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2364 throw new Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
2366 progressBarHandlers.put(new Long(id), handler);
2367 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
2368 if (handler.canCancel())
2370 JButton cancel = new JButton(
2371 MessageManager.getString("action.cancel"));
2372 final IProgressIndicator us = this;
2373 cancel.addActionListener(new ActionListener()
2376 public void actionPerformed(ActionEvent e)
2378 handler.cancelActivity(id);
2379 us.setProgressBar(MessageManager.formatMessage("label.cancelled_params", new String[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
2382 progressPanel.add(cancel, BorderLayout.EAST);
2388 * @return true if any progress bars are still active
2391 public boolean operationInProgress()
2393 if (progressBars != null && progressBars.size() > 0)
2401 * This will return the first AlignFrame viewing AlignViewport av. It will
2402 * break if there are more than one AlignFrames viewing a particular av. This
2405 * @return alignFrame for av
2407 public static AlignFrame getAlignFrameFor(AlignViewport av)
2409 if (desktop != null)
2411 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2412 for (int panel = 0; aps != null && panel < aps.length; panel++)
2414 if (aps[panel] != null && aps[panel].av == av)
2416 return aps[panel].alignFrame;
2423 public VamsasApplication getVamsasApplication()
2430 * flag set if jalview GUI is being operated programmatically
2432 private boolean inBatchMode = false;
2435 * check if jalview GUI is being operated programmatically
2437 * @return inBatchMode
2439 public boolean isInBatchMode()
2445 * set flag if jalview GUI is being operated programmatically
2447 * @param inBatchMode
2449 public void setInBatchMode(boolean inBatchMode)
2451 this.inBatchMode = inBatchMode;
2454 public void startServiceDiscovery()
2456 startServiceDiscovery(false);
2459 public void startServiceDiscovery(boolean blocking)
2461 boolean alive = true;
2462 Thread t0 = null, t1 = null, t2 = null;
2463 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2466 // todo: changesupport handlers need to be transferred
2467 if (discoverer == null)
2469 discoverer = new jalview.ws.jws1.Discoverer();
2470 // register PCS handler for desktop.
2471 discoverer.addPropertyChangeListener(changeSupport);
2473 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2474 // until we phase out completely
2475 (t0 = new Thread(discoverer)).start();
2478 // ENFIN services are EOLed as of Jalview 2.8.1 release
2483 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2485 // EnfinEnvision web service menu entries are rebuild every time the
2486 // menu is shown, so no changeSupport events are needed.
2487 jalview.ws.EnfinEnvision2OneWay.getInstance();
2488 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2491 } catch (Exception e)
2494 .info("Exception when trying to launch Envision2 workflow discovery.",
2496 Cache.log.info(e.getStackTrace());
2500 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2502 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2504 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2506 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2512 // TODO: do rest service discovery
2521 } catch (Exception e)
2524 alive = (t1 != null && t1.isAlive())
2525 || (t2 != null && t2.isAlive())
2526 || (t3 != null && t3.isAlive())
2527 || (t0 != null && t0.isAlive());
2533 * called to check if the service discovery process completed successfully.
2537 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2539 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2541 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2542 .getErrorMessages();
2545 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2547 if (serviceChangedDialog == null)
2549 // only run if we aren't already displaying one of these.
2550 addDialogThread(serviceChangedDialog = new Runnable()
2556 * JalviewDialog jd =new JalviewDialog() {
2558 * @Override protected void cancelPressed() { // TODO
2559 * Auto-generated method stub
2561 * }@Override protected void okPressed() { // TODO
2562 * Auto-generated method stub
2564 * }@Override protected void raiseClosed() { // TODO
2565 * Auto-generated method stub
2567 * } }; jd.initDialogFrame(new
2568 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2569 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2570 * + " or mis-configured HTTP proxy settings.<br/>" +
2571 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2573 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2574 * ), true, true, "Web Service Configuration Problem", 450,
2577 * jd.waitForInput();
2583 "<html><table width=\"450\"><tr><td>"
2585 + "</td></tr></table>"
2586 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2587 + " or mis-configured HTTP proxy settings.</p>"
2588 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2589 + " Tools->Preferences dialog box to change them.</p></html>"),
2590 "Web Service Configuration Problem",
2591 JOptionPane.DEFAULT_OPTION,
2592 JOptionPane.ERROR_MESSAGE);
2593 serviceChangedDialog = null;
2602 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2609 private Runnable serviceChangedDialog = null;
2612 * start a thread to open a URL in the configured browser. Pops up a warning
2613 * dialog to the user if there is an exception when calling out to the browser
2618 public static void showUrl(final String url)
2620 showUrl(url, Desktop.instance);
2624 * Like showUrl but allows progress handler to be specified
2628 * (null) or object implementing IProgressIndicator
2630 public static void showUrl(final String url,
2631 final IProgressIndicator progress)
2633 new Thread(new Runnable()
2639 if (progress != null)
2641 progress.setProgressBar(MessageManager.formatMessage("status.opening_params", new String[]{url}), this.hashCode());
2643 jalview.util.BrowserLauncher.openURL(url);
2644 } catch (Exception ex)
2647 .showInternalMessageDialog(
2649 MessageManager.getString("label.web_browser_not_found_unix"),
2650 MessageManager.getString("label.web_browser_not_found"),
2651 JOptionPane.WARNING_MESSAGE);
2653 ex.printStackTrace();
2655 if (progress != null)
2657 progress.setProgressBar(null, this.hashCode());
2663 public static WsParamSetManager wsparamManager = null;
2665 public static ParamManager getUserParameterStore()
2667 if (wsparamManager == null)
2669 wsparamManager = new WsParamSetManager();
2671 return wsparamManager;
2675 * static hyperlink handler proxy method for use by Jalview's internal windows
2679 public static void hyperlinkUpdate(HyperlinkEvent e)
2681 if (e.getEventType() == EventType.ACTIVATED)
2686 url = e.getURL().toString();
2687 Desktop.showUrl(url);
2688 } catch (Exception x)
2692 if (Cache.log != null)
2694 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2698 System.err.println("Couldn't handle string " + url
2702 // ignore any exceptions due to dud links.
2709 * single thread that handles display of dialogs to user.
2711 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2714 * flag indicating if dialogExecutor should try to acquire a permit
2716 private volatile boolean dialogPause = true;
2721 private java.util.concurrent.Semaphore block = new Semaphore(0);
2724 * add another dialog thread to the queue
2728 public void addDialogThread(final Runnable prompter)
2730 dialogExecutor.submit(new Runnable()
2739 } catch (InterruptedException x)
2744 if (instance == null)
2750 SwingUtilities.invokeAndWait(prompter);
2751 } catch (Exception q)
2753 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2759 public void startDialogQueue()
2761 // set the flag so we don't pause waiting for another permit and semaphore
2762 // the current task to begin
2763 dialogPause = false;
2767 protected void snapShotWindow_actionPerformed(ActionEvent e)
2771 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.EPS, "View of Desktop", getWidth(), getHeight(), of=new File("Jalview_snapshot"+System.currentTimeMillis()+".eps"), "View of desktop");
2773 paintAll(im.getGraphics());
2775 } catch (Exception q)
2777 Cache.log.error("Couldn't write snapshot to "+of.getAbsolutePath(),q);
2780 Cache.log.info("Successfully written snapshot to file "+of.getAbsolutePath());