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.HyperlinkEvent.EventType;
93 import javax.swing.event.MenuEvent;
94 import javax.swing.event.MenuListener;
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((screenSize.width - 900) / 2,
321 (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("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 "Couldn't locate " + url, "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, "Cut & Paste Alignment 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 Help.showHelpWindow();
1187 } catch (Exception ex)
1192 public void closeAll_actionPerformed(ActionEvent e)
1194 JInternalFrame[] frames = desktop.getAllFrames();
1195 for (int i = 0; i < frames.length; i++)
1199 frames[i].setClosed(true);
1200 } catch (java.beans.PropertyVetoException ex)
1204 System.out.println("ALL CLOSED");
1205 if (v_client != null)
1207 // TODO clear binding to vamsas document objects on close_all
1212 public void raiseRelated_actionPerformed(ActionEvent e)
1214 reorderAssociatedWindows(false, false);
1217 public void minimizeAssociated_actionPerformed(ActionEvent e)
1219 reorderAssociatedWindows(true, false);
1222 void closeAssociatedWindows()
1224 reorderAssociatedWindows(false, true);
1230 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1233 protected void garbageCollect_actionPerformed(ActionEvent e)
1235 // We simply collect the garbage
1236 jalview.bin.Cache.log.debug("Collecting garbage...");
1238 jalview.bin.Cache.log.debug("Finished garbage collection.");
1245 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1248 protected void showMemusage_actionPerformed(ActionEvent e)
1250 desktop.showMemoryUsage(showMemusage.isSelected());
1257 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1260 protected void showConsole_actionPerformed(ActionEvent e)
1262 showConsole(showConsole.isSelected());
1265 Console jconsole = null;
1268 * control whether the java console is visible or not
1272 void showConsole(boolean selected)
1274 showConsole.setSelected(selected);
1275 // TODO: decide if we should update properties file
1276 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1278 jconsole.setVisible(selected);
1281 void reorderAssociatedWindows(boolean minimize, boolean close)
1283 JInternalFrame[] frames = desktop.getAllFrames();
1284 if (frames == null || frames.length < 1)
1289 AlignViewport source = null, target = null;
1290 if (frames[0] instanceof AlignFrame)
1292 source = ((AlignFrame) frames[0]).getCurrentView();
1294 else if (frames[0] instanceof TreePanel)
1296 source = ((TreePanel) frames[0]).getViewPort();
1298 else if (frames[0] instanceof PCAPanel)
1300 source = ((PCAPanel) frames[0]).av;
1302 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1304 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1309 for (int i = 0; i < frames.length; i++)
1312 if (frames[i] == null)
1316 if (frames[i] instanceof AlignFrame)
1318 target = ((AlignFrame) frames[i]).getCurrentView();
1320 else if (frames[i] instanceof TreePanel)
1322 target = ((TreePanel) frames[i]).getViewPort();
1324 else if (frames[i] instanceof PCAPanel)
1326 target = ((PCAPanel) frames[i]).av;
1328 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1330 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1333 if (source == target)
1339 frames[i].setClosed(true);
1343 frames[i].setIcon(minimize);
1346 frames[i].toFront();
1350 } catch (java.beans.PropertyVetoException ex)
1364 protected void preferences_actionPerformed(ActionEvent e)
1375 public void saveState_actionPerformed(ActionEvent e)
1377 JalviewFileChooser chooser = new JalviewFileChooser(
1378 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1379 { "jvp" }, new String[]
1380 { "Jalview Project" }, "Jalview Project");
1382 chooser.setFileView(new JalviewFileView());
1383 chooser.setDialogTitle("Save State");
1385 int value = chooser.showSaveDialog(this);
1387 if (value == JalviewFileChooser.APPROVE_OPTION)
1389 final Desktop me = this;
1390 final java.io.File choice = chooser.getSelectedFile();
1391 new Thread(new Runnable()
1396 setProgressBar("Saving jalview project " + choice.getName(),
1398 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1399 choice.getParent());
1400 // TODO catch and handle errors for savestate
1401 // TODO prevent user from messing with the Desktop whilst we're saving
1404 new Jalview2XML().SaveState(choice);
1405 } catch (OutOfMemoryError oom)
1407 new OOMWarning("Whilst saving current state to "
1408 + choice.getName(), oom);
1409 } catch (Exception ex)
1412 "Problems whilst trying to save to " + choice.getName(),
1414 JOptionPane.showMessageDialog(
1416 "Error whilst saving current state to "
1417 + choice.getName(), "Couldn't save project",
1418 JOptionPane.WARNING_MESSAGE);
1420 setProgressBar(null, choice.hashCode());
1432 public void loadState_actionPerformed(ActionEvent e)
1434 JalviewFileChooser chooser = new JalviewFileChooser(
1435 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1436 { "jvp", "jar" }, new String[]
1437 { "Jalview Project", "Jalview Project (old)" },
1439 chooser.setFileView(new JalviewFileView());
1440 chooser.setDialogTitle("Restore state");
1442 int value = chooser.showOpenDialog(this);
1444 if (value == JalviewFileChooser.APPROVE_OPTION)
1446 final String choice = chooser.getSelectedFile().getAbsolutePath();
1447 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1448 .getSelectedFile().getParent());
1449 new Thread(new Runnable()
1453 setProgressBar("loading jalview project " + choice,
1457 new Jalview2XML().LoadJalviewAlign(choice);
1458 } catch (OutOfMemoryError oom)
1460 new OOMWarning("Whilst loading project from " + choice, oom);
1461 } catch (Exception ex)
1463 Cache.log.error("Problems whilst loading project from "
1465 JOptionPane.showMessageDialog(Desktop.desktop,
1466 "Error whilst loading project from " + choice,
1467 "Couldn't load project", JOptionPane.WARNING_MESSAGE);
1469 setProgressBar(null, choice.hashCode());
1475 public void inputSequence_actionPerformed(ActionEvent e)
1477 new SequenceFetcher(this);
1480 JPanel progressPanel;
1482 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1484 public void startLoading(final String fileName)
1486 if (fileLoadingCount == 0)
1488 fileLoadingPanels.add(addProgressPanel("Loading File: " + fileName
1494 private JPanel addProgressPanel(String string)
1496 if (progressPanel == null)
1498 progressPanel = new JPanel(new GridLayout(1, 1));
1499 totalProgressCount = 0;
1500 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1502 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1503 JProgressBar progressBar = new JProgressBar();
1504 progressBar.setIndeterminate(true);
1506 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1508 thisprogress.add(progressBar, BorderLayout.CENTER);
1509 progressPanel.add(thisprogress);
1510 ((GridLayout) progressPanel.getLayout())
1511 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1512 ++totalProgressCount;
1513 instance.validate();
1514 return thisprogress;
1517 int totalProgressCount = 0;
1519 private void removeProgressPanel(JPanel progbar)
1521 if (progressPanel != null)
1523 synchronized (progressPanel)
1525 progressPanel.remove(progbar);
1526 GridLayout gl = (GridLayout) progressPanel.getLayout();
1527 gl.setRows(gl.getRows() - 1);
1528 if (--totalProgressCount < 1)
1530 this.getContentPane().remove(progressPanel);
1531 progressPanel = null;
1538 public void stopLoading()
1541 if (fileLoadingCount < 1)
1543 while (fileLoadingPanels.size() > 0)
1545 removeProgressPanel(fileLoadingPanels.remove(0));
1547 fileLoadingPanels.clear();
1548 fileLoadingCount = 0;
1553 public static int getViewCount(String alignmentId)
1555 AlignViewport[] aps = getViewports(alignmentId);
1556 return (aps == null) ? 0 : aps.length;
1561 * @param alignmentId
1562 * @return all AlignmentPanels concerning the alignmentId sequence set
1564 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1567 if (Desktop.desktop == null)
1569 // no frames created and in headless mode
1570 // TODO: verify that frames are recoverable when in headless mode
1573 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1574 ArrayList aps = new ArrayList();
1575 for (int t = 0; t < frames.length; t++)
1577 if (frames[t] instanceof AlignFrame)
1579 AlignFrame af = (AlignFrame) frames[t];
1580 for (int a = 0; a < af.alignPanels.size(); a++)
1582 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1583 .elementAt(a)).av.getSequenceSetId()))
1585 aps.add(af.alignPanels.elementAt(a));
1590 if (aps.size() == 0)
1594 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1595 for (int t = 0; t < vap.length; t++)
1597 vap[t] = (AlignmentPanel) aps.get(t);
1603 * get all the viewports on an alignment.
1605 * @param sequenceSetId
1606 * unique alignment id
1607 * @return all viewports on the alignment bound to sequenceSetId
1609 public static AlignViewport[] getViewports(String sequenceSetId)
1611 Vector viewp = new Vector();
1612 if (desktop != null)
1614 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1616 for (int t = 0; t < frames.length; t++)
1618 if (frames[t] instanceof AlignFrame)
1620 AlignFrame afr = ((AlignFrame) frames[t]);
1621 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1623 if (afr.alignPanels != null)
1625 for (int a = 0; a < afr.alignPanels.size(); a++)
1627 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1628 .elementAt(a)).av.getSequenceSetId()))
1630 viewp.addElement(((AlignmentPanel) afr.alignPanels
1637 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1642 if (viewp.size() > 0)
1644 AlignViewport[] vp = new AlignViewport[viewp.size()];
1652 public void explodeViews(AlignFrame af)
1654 int size = af.alignPanels.size();
1660 for (int i = 0; i < size; i++)
1662 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1663 AlignFrame newaf = new AlignFrame(ap);
1664 if (ap.av.explodedPosition != null
1665 && !ap.av.explodedPosition.equals(af.getBounds()))
1667 newaf.setBounds(ap.av.explodedPosition);
1670 ap.av.gatherViewsHere = false;
1672 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1673 AlignFrame.DEFAULT_HEIGHT);
1676 af.alignPanels.clear();
1677 af.closeMenuItem_actionPerformed(true);
1681 public void gatherViews(AlignFrame source)
1683 source.viewport.gatherViewsHere = true;
1684 source.viewport.explodedPosition = source.getBounds();
1685 JInternalFrame[] frames = desktop.getAllFrames();
1686 String viewId = source.viewport.getSequenceSetId();
1688 for (int t = 0; t < frames.length; t++)
1690 if (frames[t] instanceof AlignFrame && frames[t] != source)
1692 AlignFrame af = (AlignFrame) frames[t];
1693 boolean gatherThis = false;
1694 for (int a = 0; a < af.alignPanels.size(); a++)
1696 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1697 if (viewId.equals(ap.av.getSequenceSetId()))
1700 ap.av.gatherViewsHere = false;
1701 ap.av.explodedPosition = af.getBounds();
1702 source.addAlignmentPanel(ap, false);
1708 af.alignPanels.clear();
1709 af.closeMenuItem_actionPerformed(true);
1716 jalview.gui.VamsasApplication v_client = null;
1718 public void vamsasImport_actionPerformed(ActionEvent e)
1720 if (v_client == null)
1722 // Load and try to start a session.
1723 JalviewFileChooser chooser = new JalviewFileChooser(
1724 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1726 chooser.setFileView(new JalviewFileView());
1727 chooser.setDialogTitle("Open a saved VAMSAS session");
1728 chooser.setToolTipText(MessageManager
1729 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1731 int value = chooser.showOpenDialog(this);
1733 if (value == JalviewFileChooser.APPROVE_OPTION)
1735 String fle = chooser.getSelectedFile().toString();
1736 if (!vamsasImport(chooser.getSelectedFile()))
1739 .showInternalMessageDialog(
1741 MessageManager.formatMessage(
1742 "label.couldnt_import_as_vamsas_session",
1746 .getString("label.vamsas_document_import_failed"),
1747 JOptionPane.ERROR_MESSAGE);
1753 jalview.bin.Cache.log
1754 .error("Implementation error - load session from a running session is not supported.");
1759 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1762 * @return true if import was a success and a session was started.
1764 public boolean vamsasImport(URL url)
1766 // TODO: create progress bar
1767 if (v_client != null)
1770 jalview.bin.Cache.log
1771 .error("Implementation error - load session from a running session is not supported.");
1777 // copy the URL content to a temporary local file
1778 // TODO: be a bit cleverer here with nio (?!)
1779 File file = File.createTempFile("vdocfromurl", ".vdj");
1780 FileOutputStream fos = new FileOutputStream(file);
1781 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1782 byte[] buffer = new byte[2048];
1784 while ((ln = bis.read(buffer)) > -1)
1786 fos.write(buffer, 0, ln);
1790 v_client = new jalview.gui.VamsasApplication(this, file,
1791 url.toExternalForm());
1792 } catch (Exception ex)
1794 jalview.bin.Cache.log.error(
1795 "Failed to create new vamsas session from contents of URL "
1799 setupVamsasConnectedGui();
1800 v_client.initial_update(); // TODO: thread ?
1801 return v_client.inSession();
1805 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1808 * @return true if import was a success and a session was started.
1810 public boolean vamsasImport(File file)
1812 if (v_client != null)
1815 jalview.bin.Cache.log
1816 .error("Implementation error - load session from a running session is not supported.");
1820 setProgressBar("Importing VAMSAS session from " + file.getName(),
1824 v_client = new jalview.gui.VamsasApplication(this, file, null);
1825 } catch (Exception ex)
1827 setProgressBar("Importing VAMSAS session from " + file.getName(),
1829 jalview.bin.Cache.log.error(
1830 "New vamsas session from existing session file failed:", ex);
1833 setupVamsasConnectedGui();
1834 v_client.initial_update(); // TODO: thread ?
1835 setProgressBar("Importing VAMSAS session from " + file.getName(),
1837 return v_client.inSession();
1840 public boolean joinVamsasSession(String mysesid)
1842 if (v_client != null)
1845 "Trying to join a vamsas session when another is already connected.");
1847 if (mysesid == null)
1849 throw new Error("Invalid vamsas session id.");
1851 v_client = new VamsasApplication(this, mysesid);
1852 setupVamsasConnectedGui();
1853 v_client.initial_update();
1854 return (v_client.inSession());
1857 public void vamsasStart_actionPerformed(ActionEvent e)
1859 if (v_client == null)
1862 // we just start a default session for moment.
1864 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1865 * getProperty("LAST_DIRECTORY"));
1867 * chooser.setFileView(new JalviewFileView());
1868 * chooser.setDialogTitle("Load Vamsas file");
1869 * chooser.setToolTipText("Import");
1871 * int value = chooser.showOpenDialog(this);
1873 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1874 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1876 v_client = new VamsasApplication(this);
1877 setupVamsasConnectedGui();
1878 v_client.initial_update(); // TODO: thread ?
1882 // store current data in session.
1883 v_client.push_update(); // TODO: thread
1887 protected void setupVamsasConnectedGui()
1889 vamsasStart.setText(MessageManager.getString("label.session_update"));
1890 vamsasSave.setVisible(true);
1891 vamsasStop.setVisible(true);
1892 vamsasImport.setVisible(false); // Document import to existing session is
1893 // not possible for vamsas-client-1.0.
1896 protected void setupVamsasDisconnectedGui()
1898 vamsasSave.setVisible(false);
1899 vamsasStop.setVisible(false);
1900 vamsasImport.setVisible(true);
1901 vamsasStart.setText(MessageManager
1902 .getString("label.new_vamsas_session"));
1905 public void vamsasStop_actionPerformed(ActionEvent e)
1907 if (v_client != null)
1909 v_client.end_session();
1911 setupVamsasDisconnectedGui();
1915 protected void buildVamsasStMenu()
1917 if (v_client == null)
1919 String[] sess = null;
1922 sess = VamsasApplication.getSessionList();
1923 } catch (Exception e)
1925 jalview.bin.Cache.log.warn(
1926 "Problem getting current sessions list.", e);
1931 jalview.bin.Cache.log.debug("Got current sessions list: "
1932 + sess.length + " entries.");
1933 VamsasStMenu.removeAll();
1934 for (int i = 0; i < sess.length; i++)
1936 JMenuItem sessit = new JMenuItem();
1937 sessit.setText(sess[i]);
1938 sessit.setToolTipText(MessageManager.formatMessage(
1939 "label.connect_to_session", new String[]
1941 final Desktop dsktp = this;
1942 final String mysesid = sess[i];
1943 sessit.addActionListener(new ActionListener()
1946 public void actionPerformed(ActionEvent e)
1948 if (dsktp.v_client == null)
1950 Thread rthr = new Thread(new Runnable()
1955 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1956 dsktp.setupVamsasConnectedGui();
1957 dsktp.v_client.initial_update();
1965 VamsasStMenu.add(sessit);
1967 // don't show an empty menu.
1968 VamsasStMenu.setVisible(sess.length > 0);
1973 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1974 VamsasStMenu.removeAll();
1975 VamsasStMenu.setVisible(false);
1980 // Not interested in the content. Just hide ourselves.
1981 VamsasStMenu.setVisible(false);
1985 public void vamsasSave_actionPerformed(ActionEvent e)
1987 if (v_client != null)
1989 JalviewFileChooser chooser = new JalviewFileChooser(
1990 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1991 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1993 { "Vamsas Document" }, "Vamsas Document");
1995 chooser.setFileView(new JalviewFileView());
1996 chooser.setDialogTitle("Save Vamsas Document Archive");
1998 int value = chooser.showSaveDialog(this);
2000 if (value == JalviewFileChooser.APPROVE_OPTION)
2002 java.io.File choice = chooser.getSelectedFile();
2003 JPanel progpanel = addProgressPanel("Saving VAMSAS Document to "
2004 + choice.getName());
2005 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2006 String warnmsg = null;
2007 String warnttl = null;
2010 v_client.vclient.storeDocument(choice);
2013 warnttl = "Serious Problem saving Vamsas Document";
2014 warnmsg = ex.toString();
2015 jalview.bin.Cache.log.error("Error Whilst saving document to "
2018 } catch (Exception ex)
2020 warnttl = "Problem saving Vamsas Document.";
2021 warnmsg = ex.toString();
2022 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2026 removeProgressPanel(progpanel);
2027 if (warnmsg != null)
2029 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2031 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2037 JPanel vamUpdate = null;
2040 * hide vamsas user gui bits when a vamsas document event is being handled.
2043 * true to hide gui, false to reveal gui
2045 public void setVamsasUpdate(boolean b)
2047 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2048 + (b ? "in progress" : "finished"));
2050 if (vamUpdate != null)
2052 this.removeProgressPanel(vamUpdate);
2056 vamUpdate = this.addProgressPanel("Updating vamsas session");
2058 vamsasStart.setVisible(!b);
2059 vamsasStop.setVisible(!b);
2060 vamsasSave.setVisible(!b);
2063 public JInternalFrame[] getAllFrames()
2065 return desktop.getAllFrames();
2069 * Checks the given url to see if it gives a response indicating that the user
2070 * should be informed of a new questionnaire.
2074 public void checkForQuestionnaire(String url)
2076 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2077 // javax.swing.SwingUtilities.invokeLater(jvq);
2078 new Thread(jvq).start();
2082 * Proxy class for JDesktopPane which optionally displays the current memory
2083 * usage and highlights the desktop area with a red bar if free memory runs
2088 public class MyDesktopPane extends JDesktopPane implements Runnable
2091 boolean showMemoryUsage = false;
2095 java.text.NumberFormat df;
2097 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2100 public MyDesktopPane(boolean showMemoryUsage)
2102 showMemoryUsage(showMemoryUsage);
2105 public void showMemoryUsage(boolean showMemoryUsage)
2107 this.showMemoryUsage = showMemoryUsage;
2108 if (showMemoryUsage)
2110 Thread worker = new Thread(this);
2115 public boolean isShowMemoryUsage()
2117 return showMemoryUsage;
2122 df = java.text.NumberFormat.getNumberInstance();
2123 df.setMaximumFractionDigits(2);
2124 runtime = Runtime.getRuntime();
2126 while (showMemoryUsage)
2130 maxMemory = runtime.maxMemory() / 1048576f;
2131 allocatedMemory = runtime.totalMemory() / 1048576f;
2132 freeMemory = runtime.freeMemory() / 1048576f;
2133 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2135 percentUsage = (totalFreeMemory / maxMemory) * 100;
2137 // if (percentUsage < 20)
2139 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2141 // instance.set.setBorder(border1);
2144 // sleep after showing usage
2146 } catch (Exception ex)
2148 ex.printStackTrace();
2153 public void paintComponent(Graphics g)
2155 if (showMemoryUsage && g != null && df != null)
2157 if (percentUsage < 20)
2158 g.setColor(Color.red);
2159 FontMetrics fm = g.getFontMetrics();
2162 g.drawString(MessageManager.formatMessage(
2163 "label.memory_stats",
2165 { df.format(totalFreeMemory), df.format(maxMemory),
2166 df.format(percentUsage) }), 10,
2167 getHeight() - fm.getHeight());
2174 * fixes stacking order after a modal dialog to ensure windows that should be
2175 * on top actually are
2177 public void relayerWindows()
2182 protected JMenuItem groovyShell;
2184 public void doGroovyCheck()
2186 if (jalview.bin.Cache.groovyJarsPresent())
2188 groovyShell = new JMenuItem();
2189 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2190 groovyShell.addActionListener(new ActionListener()
2192 public void actionPerformed(ActionEvent e)
2194 groovyShell_actionPerformed(e);
2197 toolsMenu.add(groovyShell);
2198 groovyShell.setVisible(true);
2203 * Accessor method to quickly get all the AlignmentFrames loaded.
2205 public static AlignFrame[] getAlignframes()
2207 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2213 Vector avp = new Vector();
2217 for (int i = frames.length - 1; i > -1; i--)
2219 if (frames[i] instanceof AlignFrame)
2221 AlignFrame af = (AlignFrame) frames[i];
2225 } catch (Exception ex)
2227 ex.printStackTrace();
2229 if (avp.size() == 0)
2233 AlignFrame afs[] = new AlignFrame[avp.size()];
2234 for (int i = 0, j = avp.size(); i < j; i++)
2236 afs[i] = (AlignFrame) avp.elementAt(i);
2242 public AppJmol[] getJmols()
2244 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2250 Vector avp = new Vector();
2254 for (int i = frames.length - 1; i > -1; i--)
2256 if (frames[i] instanceof AppJmol)
2258 AppJmol af = (AppJmol) frames[i];
2262 } catch (Exception ex)
2264 ex.printStackTrace();
2266 if (avp.size() == 0)
2270 AppJmol afs[] = new AppJmol[avp.size()];
2271 for (int i = 0, j = avp.size(); i < j; i++)
2273 afs[i] = (AppJmol) avp.elementAt(i);
2280 * Add Groovy Support to Jalview
2282 public void groovyShell_actionPerformed(ActionEvent e)
2284 // use reflection to avoid creating compilation dependency.
2285 if (!jalview.bin.Cache.groovyJarsPresent())
2288 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
2292 Class gcClass = Desktop.class.getClassLoader().loadClass(
2293 "groovy.ui.Console");
2294 Constructor gccons = gcClass.getConstructor(null);
2295 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2297 { String.class, Object.class });
2298 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2299 Object gc = gccons.newInstance(null);
2300 setvar.invoke(gc, new Object[]
2301 { "Jalview", this });
2302 run.invoke(gc, null);
2303 } catch (Exception ex)
2305 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2307 .showInternalMessageDialog(
2310 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
2311 "Jalview Groovy Support Failed",
2312 JOptionPane.ERROR_MESSAGE);
2317 * Progress bars managed by the IProgressIndicator method.
2319 private Hashtable<Long, JPanel> progressBars;
2321 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2326 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2328 public void setProgressBar(String message, long id)
2330 if (progressBars == null)
2332 progressBars = new Hashtable<Long, JPanel>();
2333 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2336 if (progressBars.get(new Long(id)) != null)
2338 JPanel progressPanel = progressBars.remove(new Long(id));
2339 if (progressBarHandlers.contains(new Long(id)))
2341 progressBarHandlers.remove(new Long(id));
2343 removeProgressPanel(progressPanel);
2347 progressBars.put(new Long(id), addProgressPanel(message));
2354 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2355 * jalview.gui.IProgressIndicatorHandler)
2357 public void registerHandler(final long id,
2358 final IProgressIndicatorHandler handler)
2360 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2363 "call setProgressBar before registering the progress bar's handler.");
2365 progressBarHandlers.put(new Long(id), handler);
2366 final JPanel progressPanel = progressBars.get(new Long(id));
2367 if (handler.canCancel())
2369 JButton cancel = new JButton(
2370 MessageManager.getString("action.cancel"));
2371 final IProgressIndicator us = this;
2372 cancel.addActionListener(new ActionListener()
2375 public void actionPerformed(ActionEvent e)
2377 handler.cancelActivity(id);
2380 + ((JLabel) progressPanel.getComponent(0))
2384 progressPanel.add(cancel, BorderLayout.EAST);
2390 * @return true if any progress bars are still active
2393 public boolean operationInProgress()
2395 if (progressBars != null && progressBars.size() > 0)
2403 * This will return the first AlignFrame viewing AlignViewport av. It will
2404 * break if there are more than one AlignFrames viewing a particular av. This
2407 * @return alignFrame for av
2409 public static AlignFrame getAlignFrameFor(AlignViewport av)
2411 if (desktop != null)
2413 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2414 for (int panel = 0; aps != null && panel < aps.length; panel++)
2416 if (aps[panel] != null && aps[panel].av == av)
2418 return aps[panel].alignFrame;
2425 public VamsasApplication getVamsasApplication()
2432 * flag set if jalview GUI is being operated programmatically
2434 private boolean inBatchMode = false;
2437 * check if jalview GUI is being operated programmatically
2439 * @return inBatchMode
2441 public boolean isInBatchMode()
2447 * set flag if jalview GUI is being operated programmatically
2449 * @param inBatchMode
2451 public void setInBatchMode(boolean inBatchMode)
2453 this.inBatchMode = inBatchMode;
2456 public void startServiceDiscovery()
2458 startServiceDiscovery(false);
2461 public void startServiceDiscovery(boolean blocking)
2463 boolean alive = true;
2464 Thread t0 = null, t1 = null, t2 = null;
2465 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2468 // todo: changesupport handlers need to be transferred
2469 if (discoverer == null)
2471 discoverer = new jalview.ws.jws1.Discoverer();
2472 // register PCS handler for desktop.
2473 discoverer.addPropertyChangeListener(changeSupport);
2475 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2476 // until we phase out completely
2477 (t0 = new Thread(discoverer)).start();
2480 // ENFIN services are EOLed as of Jalview 2.8.1 release
2485 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2487 // EnfinEnvision web service menu entries are rebuild every time the
2488 // menu is shown, so no changeSupport events are needed.
2489 jalview.ws.EnfinEnvision2OneWay.getInstance();
2490 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2493 } catch (Exception e)
2496 .info("Exception when trying to launch Envision2 workflow discovery.",
2498 Cache.log.info(e.getStackTrace());
2502 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2504 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2506 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2508 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2514 // TODO: do rest service discovery
2523 } catch (Exception e)
2526 alive = (t1 != null && t1.isAlive())
2527 || (t2 != null && t2.isAlive())
2528 || (t3 != null && t3.isAlive())
2529 || (t0 != null && t0.isAlive());
2535 * called to check if the service discovery process completed successfully.
2539 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2541 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2543 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2544 .getErrorMessages();
2547 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2549 if (serviceChangedDialog == null)
2551 // only run if we aren't already displaying one of these.
2552 addDialogThread(serviceChangedDialog = new Runnable()
2558 * JalviewDialog jd =new JalviewDialog() {
2560 * @Override protected void cancelPressed() { // TODO
2561 * Auto-generated method stub
2563 * }@Override protected void okPressed() { // TODO
2564 * Auto-generated method stub
2566 * }@Override protected void raiseClosed() { // TODO
2567 * Auto-generated method stub
2569 * } }; jd.initDialogFrame(new
2570 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2571 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2572 * + " or mis-configured HTTP proxy settings.<br/>" +
2573 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2575 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2576 * ), true, true, "Web Service Configuration Problem", 450,
2579 * jd.waitForInput();
2585 "<html><table width=\"450\"><tr><td>"
2587 + "</td></tr></table>"
2588 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2589 + " or mis-configured HTTP proxy settings.</p>"
2590 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2591 + " Tools->Preferences dialog box to change them.</p></html>"),
2592 "Web Service Configuration Problem",
2593 JOptionPane.DEFAULT_OPTION,
2594 JOptionPane.ERROR_MESSAGE);
2595 serviceChangedDialog = null;
2604 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2611 private Runnable serviceChangedDialog = null;
2614 * start a thread to open a URL in the configured browser. Pops up a warning
2615 * dialog to the user if there is an exception when calling out to the browser
2620 public static void showUrl(final String url)
2622 showUrl(url, Desktop.instance);
2626 * Like showUrl but allows progress handler to be specified
2630 * (null) or object implementing IProgressIndicator
2632 public static void showUrl(final String url,
2633 final IProgressIndicator progress)
2635 new Thread(new Runnable()
2641 if (progress != null)
2643 progress.setProgressBar("Opening " + url, this.hashCode());
2645 jalview.util.BrowserLauncher.openURL(url);
2646 } catch (Exception ex)
2649 .showInternalMessageDialog(
2651 "Unixers: Couldn't find default web browser."
2652 + "\nAdd the full path to your browser in Preferences.",
2653 "Web browser not found",
2654 JOptionPane.WARNING_MESSAGE);
2656 ex.printStackTrace();
2658 if (progress != null)
2660 progress.setProgressBar(null, this.hashCode());
2666 public static WsParamSetManager wsparamManager = null;
2668 public static ParamManager getUserParameterStore()
2670 if (wsparamManager == null)
2672 wsparamManager = new WsParamSetManager();
2674 return wsparamManager;
2678 * static hyperlink handler proxy method for use by Jalview's internal windows
2682 public static void hyperlinkUpdate(HyperlinkEvent e)
2684 if (e.getEventType() == EventType.ACTIVATED)
2689 url = e.getURL().toString();
2690 Desktop.showUrl(url);
2691 } catch (Exception x)
2695 if (Cache.log != null)
2697 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2701 System.err.println("Couldn't handle string " + url
2705 // ignore any exceptions due to dud links.
2712 * single thread that handles display of dialogs to user.
2714 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2717 * flag indicating if dialogExecutor should try to acquire a permit
2719 private volatile boolean dialogPause = true;
2724 private java.util.concurrent.Semaphore block = new Semaphore(0);
2727 * add another dialog thread to the queue
2731 public void addDialogThread(final Runnable prompter)
2733 dialogExecutor.submit(new Runnable()
2742 } catch (InterruptedException x)
2747 if (instance == null)
2753 SwingUtilities.invokeAndWait(prompter);
2754 } catch (Exception q)
2756 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2762 public void startDialogQueue()
2764 // set the flag so we don't pause waiting for another permit and semaphore
2765 // the current task to begin
2766 dialogPause = false;
2770 protected void snapShotWindow_actionPerformed(ActionEvent e)
2774 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");
2776 paintAll(im.getGraphics());
2778 } catch (Exception q)
2780 Cache.log.error("Couldn't write snapshot to "+of.getAbsolutePath(),q);
2783 Cache.log.info("Successfully written snapshot to file "+of.getAbsolutePath());