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.jbgui.GStructureViewer;
30 import jalview.structure.StructureSelectionManager;
31 import jalview.util.ImageMaker;
32 import jalview.util.MessageManager;
33 import jalview.ws.params.ParamManager;
35 import java.awt.BorderLayout;
36 import java.awt.Color;
37 import java.awt.Dimension;
38 import java.awt.FontMetrics;
39 import java.awt.Graphics;
40 import java.awt.GridLayout;
41 import java.awt.Point;
42 import java.awt.Rectangle;
43 import java.awt.Toolkit;
44 import java.awt.datatransfer.Clipboard;
45 import java.awt.datatransfer.ClipboardOwner;
46 import java.awt.datatransfer.DataFlavor;
47 import java.awt.datatransfer.Transferable;
48 import java.awt.dnd.DnDConstants;
49 import java.awt.dnd.DropTargetDragEvent;
50 import java.awt.dnd.DropTargetDropEvent;
51 import java.awt.dnd.DropTargetEvent;
52 import java.awt.dnd.DropTargetListener;
53 import java.awt.event.ActionEvent;
54 import java.awt.event.ActionListener;
55 import java.awt.event.FocusEvent;
56 import java.awt.event.FocusListener;
57 import java.awt.event.MouseAdapter;
58 import java.awt.event.MouseEvent;
59 import java.awt.event.MouseListener;
60 import java.awt.event.WindowAdapter;
61 import java.awt.event.WindowEvent;
62 import java.beans.PropertyChangeEvent;
63 import java.beans.PropertyChangeListener;
64 import java.beans.PropertyVetoException;
65 import java.io.BufferedInputStream;
67 import java.io.FileOutputStream;
68 import java.lang.reflect.Constructor;
70 import java.util.ArrayList;
71 import java.util.Hashtable;
72 import java.util.StringTokenizer;
73 import java.util.Vector;
74 import java.util.concurrent.ExecutorService;
75 import java.util.concurrent.Executors;
76 import java.util.concurrent.Semaphore;
78 import javax.swing.DefaultDesktopManager;
79 import javax.swing.DesktopManager;
80 import javax.swing.JButton;
81 import javax.swing.JComboBox;
82 import javax.swing.JComponent;
83 import javax.swing.JDesktopPane;
84 import javax.swing.JFrame;
85 import javax.swing.JInternalFrame;
86 import javax.swing.JLabel;
87 import javax.swing.JMenuItem;
88 import javax.swing.JOptionPane;
89 import javax.swing.JPanel;
90 import javax.swing.JPopupMenu;
91 import javax.swing.JProgressBar;
92 import javax.swing.SwingUtilities;
93 import javax.swing.event.HyperlinkEvent;
94 import javax.swing.event.HyperlinkEvent.EventType;
95 import javax.swing.event.MenuEvent;
96 import javax.swing.event.MenuListener;
103 * @version $Revision: 1.155 $
105 public class Desktop extends jalview.jbgui.GDesktop implements
106 DropTargetListener, ClipboardOwner, IProgressIndicator,
107 jalview.api.StructureSelectionManagerProvider
110 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
113 * news reader - null if it was never started.
115 private BlogReader jvnews = null;
117 private File projectFile;
121 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
123 public void addJalviewPropertyChangeListener(
124 PropertyChangeListener listener)
126 changeSupport.addJalviewPropertyChangeListener(listener);
130 * @param propertyName
132 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
133 * java.beans.PropertyChangeListener)
135 public void addJalviewPropertyChangeListener(String propertyName,
136 PropertyChangeListener listener)
138 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
142 * @param propertyName
144 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
145 * java.beans.PropertyChangeListener)
147 public void removeJalviewPropertyChangeListener(String propertyName,
148 PropertyChangeListener listener)
150 changeSupport.removeJalviewPropertyChangeListener(propertyName,
154 /** Singleton Desktop instance */
155 public static Desktop instance;
157 public static MyDesktopPane desktop;
159 static int openFrameCount = 0;
161 static final int xOffset = 30;
163 static final int yOffset = 30;
165 public static jalview.ws.jws1.Discoverer discoverer;
167 public static Object[] jalviewClipboard;
169 public static boolean internalCopy = false;
171 static int fileLoadingCount = 0;
173 class MyDesktopManager implements DesktopManager
176 private DesktopManager delegate;
178 public MyDesktopManager(DesktopManager delegate)
180 this.delegate = delegate;
183 public void activateFrame(JInternalFrame f)
187 delegate.activateFrame(f);
188 } catch (NullPointerException npe)
190 Point p = getMousePosition();
191 instance.showPasteMenu(p.x, p.y);
195 public void beginDraggingFrame(JComponent f)
197 delegate.beginDraggingFrame(f);
200 public void beginResizingFrame(JComponent f, int direction)
202 delegate.beginResizingFrame(f, direction);
205 public void closeFrame(JInternalFrame f)
207 delegate.closeFrame(f);
210 public void deactivateFrame(JInternalFrame f)
212 delegate.deactivateFrame(f);
215 public void deiconifyFrame(JInternalFrame f)
217 delegate.deiconifyFrame(f);
220 public void dragFrame(JComponent f, int newX, int newY)
226 delegate.dragFrame(f, newX, newY);
229 public void endDraggingFrame(JComponent f)
231 delegate.endDraggingFrame(f);
234 public void endResizingFrame(JComponent f)
236 delegate.endResizingFrame(f);
239 public void iconifyFrame(JInternalFrame f)
241 delegate.iconifyFrame(f);
244 public void maximizeFrame(JInternalFrame f)
246 delegate.maximizeFrame(f);
249 public void minimizeFrame(JInternalFrame f)
251 delegate.minimizeFrame(f);
254 public void openFrame(JInternalFrame f)
256 delegate.openFrame(f);
259 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
262 Rectangle b = desktop.getBounds();
267 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
270 public void setBoundsForFrame(JComponent f, int newX, int newY,
271 int newWidth, int newHeight)
273 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
276 // All other methods, simply delegate
281 * Creates a new Desktop object.
286 * A note to implementors. It is ESSENTIAL that any activities that might
287 * block are spawned off as threads rather than waited for during this
291 doVamsasClientCheck();
293 doConfigureStructurePrefs();
294 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
295 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
296 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
298 boolean showjconsole = jalview.bin.Cache.getDefault(
299 "SHOW_JAVA_CONSOLE", false);
300 desktop = new MyDesktopPane(selmemusage);
301 showMemusage.setSelected(selmemusage);
302 desktop.setBackground(Color.white);
303 getContentPane().setLayout(new BorderLayout());
304 // alternate config - have scrollbars - see notes in JAL-153
305 // JScrollPane sp = new JScrollPane();
306 // sp.getViewport().setView(desktop);
307 // getContentPane().add(sp, BorderLayout.CENTER);
308 getContentPane().add(desktop, BorderLayout.CENTER);
309 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
311 // This line prevents Windows Look&Feel resizing all new windows to maximum
312 // if previous window was maximised
313 desktop.setDesktopManager(new MyDesktopManager(
314 new DefaultDesktopManager()));
316 Rectangle dims = getLastKnownDimensions("");
323 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
324 setBounds((screenSize.width - 900) / 2,
325 (screenSize.height - 650) / 2, 900, 650);
327 jconsole = new Console(this, showjconsole);
328 // add essential build information
329 jconsole.setHeader("Jalview Version: "
330 + jalview.bin.Cache.getProperty("VERSION") + "\n"
331 + "Jalview Installation: "
332 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
335 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
336 + "Java version: " + System.getProperty("java.version") + "\n"
337 + System.getProperty("os.arch") + " "
338 + System.getProperty("os.name") + " "
339 + System.getProperty("os.version"));
341 showConsole(showjconsole);
343 showNews.setVisible(false);
345 this.addWindowListener(new WindowAdapter()
347 public void windowClosing(WindowEvent evt)
354 this.addMouseListener(ma = new MouseAdapter()
356 public void mousePressed(MouseEvent evt)
358 if (SwingUtilities.isRightMouseButton(evt))
360 showPasteMenu(evt.getX(), evt.getY());
364 desktop.addMouseListener(ma);
366 this.addFocusListener(new FocusListener()
370 public void focusLost(FocusEvent e)
372 // TODO Auto-generated method stub
377 public void focusGained(FocusEvent e)
379 Cache.log.debug("Relaying windows after focus gain");
380 // make sure that we sort windows properly after we gain focus
381 instance.relayerWindows();
384 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
385 // Spawn a thread that shows the splashscreen
386 SwingUtilities.invokeLater(new Runnable()
395 // Thread off a new instance of the file chooser - this reduces the time it
396 // takes to open it later on.
397 new Thread(new Runnable()
401 Cache.log.debug("Filechooser init thread started.");
402 JalviewFileChooser chooser = new JalviewFileChooser(
403 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
404 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
405 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
406 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
407 Cache.log.debug("Filechooser init thread finished.");
410 // Add the service change listener
411 changeSupport.addJalviewPropertyChangeListener("services",
412 new PropertyChangeListener()
416 public void propertyChange(PropertyChangeEvent evt)
418 Cache.log.debug("Firing service changed event for "
419 + evt.getNewValue());
420 JalviewServicesChanged(evt);
426 public void doConfigureStructurePrefs()
428 // configure services
429 StructureSelectionManager ssm = StructureSelectionManager
430 .getStructureSelectionManager(this);
431 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
433 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
434 Preferences.ADD_TEMPFACT_ANN, true));
435 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(Preferences.STRUCT_FROM_PDB, true));
436 ssm.setSecStructServices(jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW,
441 ssm.setAddTempFacAnnot(false);
442 ssm.setProcessSecondaryStructure(false);
443 ssm.setSecStructServices(false);
447 public void checkForNews()
449 final Desktop me = this;
450 // Thread off the news reader, in case there are connection problems.
451 addDialogThread(new Runnable()
456 Cache.log.debug("Starting news thread.");
458 jvnews = new BlogReader(me);
459 showNews.setVisible(true);
460 Cache.log.debug("Completed news thread.");
465 protected void showNews_actionPerformed(ActionEvent e)
467 showNews(showNews.isSelected());
470 void showNews(boolean visible)
473 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
474 showNews.setSelected(visible);
475 if (visible && !jvnews.isVisible())
477 new Thread(new Runnable()
482 long instance = System.currentTimeMillis();
483 Desktop.instance.setProgressBar(MessageManager.getString("status.refreshing_news"), instance);
484 jvnews.refreshNews();
485 Desktop.instance.setProgressBar(null, instance);
494 * recover the last known dimensions for a jalview window
497 * - empty string is desktop, all other windows have unique prefix
498 * @return null or last known dimensions scaled to current geometry (if last
499 * window geom was known)
501 Rectangle getLastKnownDimensions(String windowName)
503 // TODO: lock aspect ratio for scaling desktop Bug #0058199
504 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
505 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
506 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
507 String width = jalview.bin.Cache.getProperty(windowName
509 String height = jalview.bin.Cache.getProperty(windowName
511 if ((x != null) && (y != null) && (width != null) && (height != null))
513 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
514 .parseInt(width), ih = Integer.parseInt(height);
515 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
517 // attempt #1 - try to cope with change in screen geometry - this
518 // version doesn't preserve original jv aspect ratio.
519 // take ratio of current screen size vs original screen size.
520 double sw = ((1f * screenSize.width) / (1f * Integer
521 .parseInt(jalview.bin.Cache
522 .getProperty("SCREENGEOMETRY_WIDTH"))));
523 double sh = ((1f * screenSize.height) / (1f * Integer
524 .parseInt(jalview.bin.Cache
525 .getProperty("SCREENGEOMETRY_HEIGHT"))));
526 // rescale the bounds depending upon the current screen geometry.
527 ix = (int) (ix * sw);
528 iw = (int) (iw * sw);
529 iy = (int) (iy * sh);
530 ih = (int) (ih * sh);
531 while (ix >= screenSize.width)
533 jalview.bin.Cache.log
534 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
535 ix -= screenSize.width;
537 while (iy >= screenSize.height)
539 jalview.bin.Cache.log
540 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
541 iy -= screenSize.height;
543 jalview.bin.Cache.log.debug("Got last known dimensions for "
544 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
547 // return dimensions for new instance
548 return new Rectangle(ix, iy, iw, ih);
553 private void doVamsasClientCheck()
555 if (jalview.bin.Cache.vamsasJarsPresent())
557 setupVamsasDisconnectedGui();
558 VamsasMenu.setVisible(true);
559 final Desktop us = this;
560 VamsasMenu.addMenuListener(new MenuListener()
562 // this listener remembers when the menu was first selected, and
563 // doesn't rebuild the session list until it has been cleared and
565 boolean refresh = true;
567 public void menuCanceled(MenuEvent e)
572 public void menuDeselected(MenuEvent e)
577 public void menuSelected(MenuEvent e)
581 us.buildVamsasStMenu();
586 vamsasStart.setVisible(true);
590 void showPasteMenu(int x, int y)
592 JPopupMenu popup = new JPopupMenu();
593 JMenuItem item = new JMenuItem(
594 MessageManager.getString("label.paste_new_window"));
595 item.addActionListener(new ActionListener()
597 public void actionPerformed(ActionEvent evt)
604 popup.show(this, x, y);
611 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
612 Transferable contents = c.getContents(this);
614 if (contents != null)
616 String file = (String) contents
617 .getTransferData(DataFlavor.stringFlavor);
619 String format = new IdentifyFile().Identify(file,
620 FormatAdapter.PASTE);
622 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
625 } catch (Exception ex)
628 .println("Unable to paste alignment from system clipboard:\n"
634 * Adds and opens the given frame to the desktop
645 public static synchronized void addInternalFrame(
646 final JInternalFrame frame, String title, int w, int h)
648 addInternalFrame(frame, title, true, w, h, true);
653 * Add an internal frame to the Jalview desktop
660 * When true, display frame immediately, otherwise, caller must call
661 * setVisible themselves.
667 public static synchronized void addInternalFrame(
668 final JInternalFrame frame, String title, boolean makeVisible,
671 addInternalFrame(frame, title, makeVisible, w, h, true);
675 * Add an internal frame to the Jalview desktop and make it visible
688 public static synchronized void addInternalFrame(
689 final JInternalFrame frame, String title, int w, int h,
692 addInternalFrame(frame, title, true, w, h, resizable);
696 * Add an internal frame to the Jalview desktop
703 * When true, display frame immediately, otherwise, caller must call
704 * setVisible themselves.
712 public static synchronized void addInternalFrame(
713 final JInternalFrame frame, String title, boolean makeVisible,
714 int w, int h, boolean resizable)
717 // TODO: allow callers to determine X and Y position of frame (eg. via
719 // TODO: consider fixing method to update entries in the window submenu with
720 // the current window title
722 frame.setTitle(title);
723 if (frame.getWidth() < 1 || frame.getHeight() < 1)
727 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
728 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
729 // IF JALVIEW IS RUNNING HEADLESS
730 // ///////////////////////////////////////////////
732 || (System.getProperty("java.awt.headless") != null && System
733 .getProperty("java.awt.headless").equals("true")))
740 frame.setVisible(makeVisible);
741 frame.setClosable(true);
742 frame.setResizable(resizable);
743 frame.setMaximizable(resizable);
744 frame.setIconifiable(resizable);
745 frame.setFrameIcon(null);
747 if (frame.getX() < 1 && frame.getY() < 1)
749 frame.setLocation(xOffset * openFrameCount, yOffset
750 * ((openFrameCount - 1) % 10) + yOffset);
753 final JMenuItem menuItem = new JMenuItem(title);
754 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
756 public void internalFrameActivated(
757 javax.swing.event.InternalFrameEvent evt)
759 JInternalFrame itf = desktop.getSelectedFrame();
767 public void internalFrameClosed(
768 javax.swing.event.InternalFrameEvent evt)
770 PaintRefresher.RemoveComponent(frame);
772 windowMenu.remove(menuItem);
773 JInternalFrame itf = desktop.getSelectedFrame();
782 menuItem.addActionListener(new ActionListener()
784 public void actionPerformed(ActionEvent e)
788 frame.setSelected(true);
789 frame.setIcon(false);
790 } catch (java.beans.PropertyVetoException ex)
796 menuItem.addMouseListener(new MouseListener()
800 public void mouseReleased(MouseEvent e)
805 public void mousePressed(MouseEvent e)
810 public void mouseExited(MouseEvent e)
814 frame.setSelected(false);
815 } catch (PropertyVetoException e1)
821 public void mouseEntered(MouseEvent e)
825 frame.setSelected(true);
826 } catch (PropertyVetoException e1)
832 public void mouseClicked(MouseEvent e)
838 windowMenu.add(menuItem);
844 frame.setSelected(true);
845 frame.requestFocus();
846 } catch (java.beans.PropertyVetoException ve)
848 } catch (java.lang.ClassCastException cex)
851 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
856 public void lostOwnership(Clipboard clipboard, Transferable contents)
860 Desktop.jalviewClipboard = null;
863 internalCopy = false;
866 public void dragEnter(DropTargetDragEvent evt)
870 public void dragExit(DropTargetEvent evt)
874 public void dragOver(DropTargetDragEvent evt)
878 public void dropActionChanged(DropTargetDragEvent evt)
888 public void drop(DropTargetDropEvent evt)
890 boolean success = true;
891 Transferable t = evt.getTransferable();
892 java.util.List files = null;
893 java.util.List protocols = null;
897 DataFlavor uriListFlavor = new DataFlavor(
898 "text/uri-list;class=java.lang.String");
899 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
901 // Works on Windows and MacOSX
902 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
903 files = (java.util.List) t
904 .getTransferData(DataFlavor.javaFileListFlavor);
906 else if (t.isDataFlavorSupported(uriListFlavor))
908 // This is used by Unix drag system
909 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
910 String data = (String) t.getTransferData(uriListFlavor);
911 files = new java.util.ArrayList(1);
912 protocols = new java.util.ArrayList(1);
913 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
914 data, "\r\n"); st.hasMoreTokens();)
916 String s = st.nextToken();
917 if (s.startsWith("#"))
919 // the line is a comment (as per the RFC 2483)
922 java.net.URI uri = new java.net.URI(s);
923 if (uri.getScheme().toLowerCase().startsWith("http"))
925 protocols.add(FormatAdapter.URL);
926 files.add(uri.toString());
930 // otherwise preserve old behaviour: catch all for file objects
931 java.io.File file = new java.io.File(uri);
932 protocols.add(FormatAdapter.FILE);
933 files.add(file.toString());
937 } catch (Exception e)
946 for (int i = 0; i < files.size(); i++)
948 String file = files.get(i).toString();
949 String protocol = (protocols == null) ? FormatAdapter.FILE
950 : (String) protocols.get(i);
951 String format = null;
953 if (file.endsWith(".jar"))
960 format = new IdentifyFile().Identify(file, protocol);
963 new FileLoader().LoadFile(file, protocol, format);
966 } catch (Exception ex)
971 evt.dropComplete(success); // need this to ensure input focus is properly
972 // transfered to any new windows created
981 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
983 JalviewFileChooser chooser = new JalviewFileChooser(
984 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
985 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
986 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
987 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
989 chooser.setFileView(new JalviewFileView());
990 chooser.setDialogTitle(MessageManager
991 .getString("label.open_local_file"));
992 chooser.setToolTipText(MessageManager.getString("action.open"));
994 int value = chooser.showOpenDialog(this);
996 if (value == JalviewFileChooser.APPROVE_OPTION)
998 String choice = chooser.getSelectedFile().getPath();
999 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1000 .getSelectedFile().getParent());
1002 String format = null;
1003 if (chooser.getSelectedFormat() != null
1004 && chooser.getSelectedFormat().equals("Jalview"))
1010 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
1013 if (viewport != null)
1015 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
1020 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
1031 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1033 // This construct allows us to have a wider textfield
1035 JLabel label = new JLabel(
1036 MessageManager.getString("label.input_file_url"));
1037 final JComboBox history = new JComboBox();
1039 JPanel panel = new JPanel(new GridLayout(2, 1));
1042 history.setPreferredSize(new Dimension(400, 20));
1043 history.setEditable(true);
1044 history.addItem("http://www.");
1046 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1050 if (historyItems != null)
1052 st = new StringTokenizer(historyItems, "\t");
1054 while (st.hasMoreTokens())
1056 history.addItem(st.nextElement());
1060 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
1061 MessageManager.getString("label.input_alignment_from_url"),
1062 JOptionPane.OK_CANCEL_OPTION);
1064 if (reply != JOptionPane.OK_OPTION)
1069 String url = history.getSelectedItem().toString();
1071 if (url.toLowerCase().endsWith(".jar"))
1073 if (viewport != null)
1075 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1080 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1085 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1087 if (format.equals("URL NOT FOUND"))
1089 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1090 MessageManager.formatMessage("label.couldnt_locate", new String[]{url}), MessageManager.getString("label.url_not_found"),
1091 JOptionPane.WARNING_MESSAGE);
1096 if (viewport != null)
1098 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1102 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1113 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1115 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1116 cap.setForInput(viewport);
1117 Desktop.addInternalFrame(cap,
1118 MessageManager.getString("label.cut_paste_alignmen_file"),
1127 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1129 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1130 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1132 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1133 getBounds().y, getWidth(), getHeight()));
1135 if (jconsole != null)
1137 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1138 jconsole.stopConsole();
1142 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1145 if (dialogExecutor != null)
1147 dialogExecutor.shutdownNow();
1153 private void storeLastKnownDimensions(String string, Rectangle jc)
1155 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1156 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1157 + " height:" + jc.height);
1159 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1160 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1161 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1162 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1171 public void aboutMenuItem_actionPerformed(ActionEvent e)
1173 // StringBuffer message = getAboutMessage(false);
1174 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1176 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1177 new Thread(new Runnable()
1181 new SplashScreen(true);
1186 public StringBuffer getAboutMessage(boolean shortv)
1188 StringBuffer message = new StringBuffer();
1189 message.append("<html>");
1192 message.append("<h1><strong>Version: "
1193 + jalview.bin.Cache.getProperty("VERSION")
1194 + "</strong></h1>");
1195 message.append("<strong>Last Updated: <em>"
1196 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1197 + "</em></strong>");
1203 message.append("<strong>Version "
1204 + jalview.bin.Cache.getProperty("VERSION")
1205 + "; last updated: "
1206 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1209 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1212 message.append("<br>...Checking latest version...</br>");
1214 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1215 .equals(jalview.bin.Cache.getProperty("VERSION")))
1217 boolean red = false;
1218 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1219 .indexOf("automated build") == -1)
1222 // Displayed when code version and jnlp version do not match and code
1223 // version is not a development build
1224 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1227 message.append("<br>!! Version "
1228 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1230 + " is available for download from "
1231 + jalview.bin.Cache.getDefault("www.jalview.org",
1232 "http://www.jalview.org") + " !!");
1235 message.append("</div>");
1238 message.append("<br>Authors: "
1242 "The Jalview Authors (See AUTHORS file for current list)")
1243 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1244 + "<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"
1245 + "<br><br>If you use Jalview, please cite:"
1246 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1247 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1248 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1259 public void documentationMenuItem_actionPerformed(ActionEvent e)
1263 Help.showHelpWindow();
1264 } catch (Exception ex)
1269 public void closeAll_actionPerformed(ActionEvent e)
1271 JInternalFrame[] frames = desktop.getAllFrames();
1272 for (int i = 0; i < frames.length; i++)
1276 frames[i].setClosed(true);
1277 } catch (java.beans.PropertyVetoException ex)
1281 System.out.println("ALL CLOSED");
1282 if (v_client != null)
1284 // TODO clear binding to vamsas document objects on close_all
1289 public void raiseRelated_actionPerformed(ActionEvent e)
1291 reorderAssociatedWindows(false, false);
1294 public void minimizeAssociated_actionPerformed(ActionEvent e)
1296 reorderAssociatedWindows(true, false);
1299 void closeAssociatedWindows()
1301 reorderAssociatedWindows(false, true);
1307 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1310 protected void garbageCollect_actionPerformed(ActionEvent e)
1312 // We simply collect the garbage
1313 jalview.bin.Cache.log.debug("Collecting garbage...");
1315 jalview.bin.Cache.log.debug("Finished garbage collection.");
1322 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1325 protected void showMemusage_actionPerformed(ActionEvent e)
1327 desktop.showMemoryUsage(showMemusage.isSelected());
1334 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1337 protected void showConsole_actionPerformed(ActionEvent e)
1339 showConsole(showConsole.isSelected());
1342 Console jconsole = null;
1345 * control whether the java console is visible or not
1349 void showConsole(boolean selected)
1351 showConsole.setSelected(selected);
1352 // TODO: decide if we should update properties file
1353 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1355 jconsole.setVisible(selected);
1358 void reorderAssociatedWindows(boolean minimize, boolean close)
1360 JInternalFrame[] frames = desktop.getAllFrames();
1361 if (frames == null || frames.length < 1)
1366 AlignViewport source = null, target = null;
1367 if (frames[0] instanceof AlignFrame)
1369 source = ((AlignFrame) frames[0]).getCurrentView();
1371 else if (frames[0] instanceof TreePanel)
1373 source = ((TreePanel) frames[0]).getViewPort();
1375 else if (frames[0] instanceof PCAPanel)
1377 source = ((PCAPanel) frames[0]).av;
1379 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1381 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1386 for (int i = 0; i < frames.length; i++)
1389 if (frames[i] == null)
1393 if (frames[i] instanceof AlignFrame)
1395 target = ((AlignFrame) frames[i]).getCurrentView();
1397 else if (frames[i] instanceof TreePanel)
1399 target = ((TreePanel) frames[i]).getViewPort();
1401 else if (frames[i] instanceof PCAPanel)
1403 target = ((PCAPanel) frames[i]).av;
1405 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1407 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1410 if (source == target)
1416 frames[i].setClosed(true);
1420 frames[i].setIcon(minimize);
1423 frames[i].toFront();
1427 } catch (java.beans.PropertyVetoException ex)
1441 protected void preferences_actionPerformed(ActionEvent e)
1452 public void saveState_actionPerformed(ActionEvent e)
1454 JalviewFileChooser chooser = new JalviewFileChooser(
1455 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1456 { "jvp" }, new String[]
1457 { "Jalview Project" }, "Jalview Project");
1459 chooser.setFileView(new JalviewFileView());
1460 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1462 int value = chooser.showSaveDialog(this);
1464 if (value == JalviewFileChooser.APPROVE_OPTION)
1466 final Desktop me = this;
1467 final java.io.File choice = chooser.getSelectedFile();
1468 setProjectFile(choice);
1470 // TODO or move inside the new Thread?
1471 saveChimeraSessions(choice.getAbsolutePath());
1473 new Thread(new Runnable()
1478 setProgressBar(MessageManager.formatMessage("label.saving_jalview_project", new String[]{choice.getName()}),
1480 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1481 choice.getParent());
1482 // TODO catch and handle errors for savestate
1483 // TODO prevent user from messing with the Desktop whilst we're saving
1486 new Jalview2XML().saveState(choice);
1487 } catch (OutOfMemoryError oom)
1489 new OOMWarning("Whilst saving current state to "
1490 + choice.getName(), oom);
1491 } catch (Exception ex)
1494 "Problems whilst trying to save to " + choice.getName(),
1496 JOptionPane.showMessageDialog(
1498 MessageManager.formatMessage("label.error_whilst_saving_current_state_to", new String[]{ choice.getName()}),
1499 MessageManager.getString("label.couldnt_save_project"),
1500 JOptionPane.WARNING_MESSAGE);
1502 setProgressBar(null, choice.hashCode());
1509 * Request any open, linked Chimera sessions to save their state.
1511 * @param jalviewProjectFilename
1512 * the filename of the Jalview project; Chimera session files should
1513 * be given distinct, but obviously related, names.
1515 public void saveChimeraSessions(String jalviewProjectFilename)
1518 for (JInternalFrame frame : getAllFrames())
1520 if (frame instanceof ChimeraViewFrame)
1523 * Construct a filename for the Chimera session by append _chimera<n>.py
1524 * to the Jalview project file name.
1526 String chimeraPath = jalviewProjectFilename + "_chimera_" + i
1528 ((ChimeraViewFrame) frame).saveSession(chimeraPath);
1534 private void setProjectFile(File choice)
1536 this.projectFile = choice;
1539 public File getProjectFile()
1541 return this.projectFile;
1550 public void loadState_actionPerformed(ActionEvent e)
1552 JalviewFileChooser chooser = new JalviewFileChooser(
1553 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
1554 { "jvp", "jar" }, new String[]
1555 { "Jalview Project", "Jalview Project (old)" },
1557 chooser.setFileView(new JalviewFileView());
1558 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1560 int value = chooser.showOpenDialog(this);
1562 if (value == JalviewFileChooser.APPROVE_OPTION)
1564 final File selectedFile = chooser.getSelectedFile();
1565 setProjectFile(selectedFile);
1566 final String choice = selectedFile.getAbsolutePath();
1567 jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1568 new Thread(new Runnable()
1572 setProgressBar(MessageManager.formatMessage("label.loading_jalview_project", new String[]{choice}),
1576 new Jalview2XML().loadJalviewAlign(choice);
1577 } catch (OutOfMemoryError oom)
1579 new OOMWarning("Whilst loading project from " + choice, oom);
1580 } catch (Exception ex)
1582 Cache.log.error("Problems whilst loading project from "
1584 JOptionPane.showMessageDialog(Desktop.desktop,
1585 MessageManager.formatMessage("label.error_whilst_loading_project_from", new String[]{choice}),
1586 MessageManager.getString("label.couldnt_load_project"), JOptionPane.WARNING_MESSAGE);
1588 setProgressBar(null, choice.hashCode());
1594 public void inputSequence_actionPerformed(ActionEvent e)
1596 new SequenceFetcher(this);
1599 JPanel progressPanel;
1601 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1603 public void startLoading(final String fileName)
1605 if (fileLoadingCount == 0)
1607 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage("label.loading_file", new String[]{fileName})));
1612 private JPanel addProgressPanel(String string)
1614 if (progressPanel == null)
1616 progressPanel = new JPanel(new GridLayout(1, 1));
1617 totalProgressCount = 0;
1618 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1620 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1621 JProgressBar progressBar = new JProgressBar();
1622 progressBar.setIndeterminate(true);
1624 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1626 thisprogress.add(progressBar, BorderLayout.CENTER);
1627 progressPanel.add(thisprogress);
1628 ((GridLayout) progressPanel.getLayout())
1629 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1630 ++totalProgressCount;
1631 instance.validate();
1632 return thisprogress;
1635 int totalProgressCount = 0;
1637 private void removeProgressPanel(JPanel progbar)
1639 if (progressPanel != null)
1641 synchronized (progressPanel)
1643 progressPanel.remove(progbar);
1644 GridLayout gl = (GridLayout) progressPanel.getLayout();
1645 gl.setRows(gl.getRows() - 1);
1646 if (--totalProgressCount < 1)
1648 this.getContentPane().remove(progressPanel);
1649 progressPanel = null;
1656 public void stopLoading()
1659 if (fileLoadingCount < 1)
1661 while (fileLoadingPanels.size() > 0)
1663 removeProgressPanel(fileLoadingPanels.remove(0));
1665 fileLoadingPanels.clear();
1666 fileLoadingCount = 0;
1671 public static int getViewCount(String alignmentId)
1673 AlignViewport[] aps = getViewports(alignmentId);
1674 return (aps == null) ? 0 : aps.length;
1679 * @param alignmentId
1680 * @return all AlignmentPanels concerning the alignmentId sequence set
1682 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1685 if (Desktop.desktop == null)
1687 // no frames created and in headless mode
1688 // TODO: verify that frames are recoverable when in headless mode
1691 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1692 ArrayList aps = new ArrayList();
1693 for (int t = 0; t < frames.length; t++)
1695 if (frames[t] instanceof AlignFrame)
1697 AlignFrame af = (AlignFrame) frames[t];
1698 for (int a = 0; a < af.alignPanels.size(); a++)
1700 if (alignmentId.equals(((AlignmentPanel) af.alignPanels
1701 .elementAt(a)).av.getSequenceSetId()))
1703 aps.add(af.alignPanels.elementAt(a));
1708 if (aps.size() == 0)
1712 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1713 for (int t = 0; t < vap.length; t++)
1715 vap[t] = (AlignmentPanel) aps.get(t);
1721 * get all the viewports on an alignment.
1723 * @param sequenceSetId
1724 * unique alignment id
1725 * @return all viewports on the alignment bound to sequenceSetId
1727 public static AlignViewport[] getViewports(String sequenceSetId)
1729 Vector viewp = new Vector();
1730 if (desktop != null)
1732 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1734 for (int t = 0; t < frames.length; t++)
1736 if (frames[t] instanceof AlignFrame)
1738 AlignFrame afr = ((AlignFrame) frames[t]);
1739 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1741 if (afr.alignPanels != null)
1743 for (int a = 0; a < afr.alignPanels.size(); a++)
1745 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1746 .elementAt(a)).av.getSequenceSetId()))
1748 viewp.addElement(((AlignmentPanel) afr.alignPanels
1755 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1760 if (viewp.size() > 0)
1762 AlignViewport[] vp = new AlignViewport[viewp.size()];
1770 public void explodeViews(AlignFrame af)
1772 int size = af.alignPanels.size();
1778 for (int i = 0; i < size; i++)
1780 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1781 AlignFrame newaf = new AlignFrame(ap);
1782 if (ap.av.explodedPosition != null
1783 && !ap.av.explodedPosition.equals(af.getBounds()))
1785 newaf.setBounds(ap.av.explodedPosition);
1788 ap.av.gatherViewsHere = false;
1790 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1791 AlignFrame.DEFAULT_HEIGHT);
1794 af.alignPanels.clear();
1795 af.closeMenuItem_actionPerformed(true);
1799 public void gatherViews(AlignFrame source)
1801 source.viewport.gatherViewsHere = true;
1802 source.viewport.explodedPosition = source.getBounds();
1803 JInternalFrame[] frames = desktop.getAllFrames();
1804 String viewId = source.viewport.getSequenceSetId();
1806 for (int t = 0; t < frames.length; t++)
1808 if (frames[t] instanceof AlignFrame && frames[t] != source)
1810 AlignFrame af = (AlignFrame) frames[t];
1811 boolean gatherThis = false;
1812 for (int a = 0; a < af.alignPanels.size(); a++)
1814 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1815 if (viewId.equals(ap.av.getSequenceSetId()))
1818 ap.av.gatherViewsHere = false;
1819 ap.av.explodedPosition = af.getBounds();
1820 source.addAlignmentPanel(ap, false);
1826 af.alignPanels.clear();
1827 af.closeMenuItem_actionPerformed(true);
1834 jalview.gui.VamsasApplication v_client = null;
1836 public void vamsasImport_actionPerformed(ActionEvent e)
1838 if (v_client == null)
1840 // Load and try to start a session.
1841 JalviewFileChooser chooser = new JalviewFileChooser(
1842 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1844 chooser.setFileView(new JalviewFileView());
1845 chooser.setDialogTitle(MessageManager.getString("label.open_saved_vamsas_session"));
1846 chooser.setToolTipText(MessageManager
1847 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1849 int value = chooser.showOpenDialog(this);
1851 if (value == JalviewFileChooser.APPROVE_OPTION)
1853 String fle = chooser.getSelectedFile().toString();
1854 if (!vamsasImport(chooser.getSelectedFile()))
1857 .showInternalMessageDialog(
1859 MessageManager.formatMessage(
1860 "label.couldnt_import_as_vamsas_session",
1864 .getString("label.vamsas_document_import_failed"),
1865 JOptionPane.ERROR_MESSAGE);
1871 jalview.bin.Cache.log
1872 .error("Implementation error - load session from a running session is not supported.");
1877 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1880 * @return true if import was a success and a session was started.
1882 public boolean vamsasImport(URL url)
1884 // TODO: create progress bar
1885 if (v_client != null)
1888 jalview.bin.Cache.log
1889 .error("Implementation error - load session from a running session is not supported.");
1895 // copy the URL content to a temporary local file
1896 // TODO: be a bit cleverer here with nio (?!)
1897 File file = File.createTempFile("vdocfromurl", ".vdj");
1898 FileOutputStream fos = new FileOutputStream(file);
1899 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1900 byte[] buffer = new byte[2048];
1902 while ((ln = bis.read(buffer)) > -1)
1904 fos.write(buffer, 0, ln);
1908 v_client = new jalview.gui.VamsasApplication(this, file,
1909 url.toExternalForm());
1910 } catch (Exception ex)
1912 jalview.bin.Cache.log.error(
1913 "Failed to create new vamsas session from contents of URL "
1917 setupVamsasConnectedGui();
1918 v_client.initial_update(); // TODO: thread ?
1919 return v_client.inSession();
1923 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1926 * @return true if import was a success and a session was started.
1928 public boolean vamsasImport(File file)
1930 if (v_client != null)
1933 jalview.bin.Cache.log
1934 .error("Implementation error - load session from a running session is not supported.");
1938 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1942 v_client = new jalview.gui.VamsasApplication(this, file, null);
1943 } catch (Exception ex)
1945 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1947 jalview.bin.Cache.log.error(
1948 "New vamsas session from existing session file failed:", ex);
1951 setupVamsasConnectedGui();
1952 v_client.initial_update(); // TODO: thread ?
1953 setProgressBar(MessageManager.formatMessage("status.importing_vamsas_session_from", new String[]{file.getName()}),
1955 return v_client.inSession();
1958 public boolean joinVamsasSession(String mysesid)
1960 if (v_client != null)
1962 throw new Error(MessageManager.getString("error.try_join_vamsas_session_another"));
1964 if (mysesid == null)
1966 throw new Error(MessageManager.getString("error.invalid_vamsas_session_id"));
1968 v_client = new VamsasApplication(this, mysesid);
1969 setupVamsasConnectedGui();
1970 v_client.initial_update();
1971 return (v_client.inSession());
1974 public void vamsasStart_actionPerformed(ActionEvent e)
1976 if (v_client == null)
1979 // we just start a default session for moment.
1981 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1982 * getProperty("LAST_DIRECTORY"));
1984 * chooser.setFileView(new JalviewFileView());
1985 * chooser.setDialogTitle("Load Vamsas file");
1986 * chooser.setToolTipText("Import");
1988 * int value = chooser.showOpenDialog(this);
1990 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1991 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1993 v_client = new VamsasApplication(this);
1994 setupVamsasConnectedGui();
1995 v_client.initial_update(); // TODO: thread ?
1999 // store current data in session.
2000 v_client.push_update(); // TODO: thread
2004 protected void setupVamsasConnectedGui()
2006 vamsasStart.setText(MessageManager.getString("label.session_update"));
2007 vamsasSave.setVisible(true);
2008 vamsasStop.setVisible(true);
2009 vamsasImport.setVisible(false); // Document import to existing session is
2010 // not possible for vamsas-client-1.0.
2013 protected void setupVamsasDisconnectedGui()
2015 vamsasSave.setVisible(false);
2016 vamsasStop.setVisible(false);
2017 vamsasImport.setVisible(true);
2018 vamsasStart.setText(MessageManager
2019 .getString("label.new_vamsas_session"));
2022 public void vamsasStop_actionPerformed(ActionEvent e)
2024 if (v_client != null)
2026 v_client.end_session();
2028 setupVamsasDisconnectedGui();
2032 protected void buildVamsasStMenu()
2034 if (v_client == null)
2036 String[] sess = null;
2039 sess = VamsasApplication.getSessionList();
2040 } catch (Exception e)
2042 jalview.bin.Cache.log.warn(
2043 "Problem getting current sessions list.", e);
2048 jalview.bin.Cache.log.debug("Got current sessions list: "
2049 + sess.length + " entries.");
2050 VamsasStMenu.removeAll();
2051 for (int i = 0; i < sess.length; i++)
2053 JMenuItem sessit = new JMenuItem();
2054 sessit.setText(sess[i]);
2055 sessit.setToolTipText(MessageManager.formatMessage(
2056 "label.connect_to_session", new String[]
2058 final Desktop dsktp = this;
2059 final String mysesid = sess[i];
2060 sessit.addActionListener(new ActionListener()
2063 public void actionPerformed(ActionEvent e)
2065 if (dsktp.v_client == null)
2067 Thread rthr = new Thread(new Runnable()
2072 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2073 dsktp.setupVamsasConnectedGui();
2074 dsktp.v_client.initial_update();
2082 VamsasStMenu.add(sessit);
2084 // don't show an empty menu.
2085 VamsasStMenu.setVisible(sess.length > 0);
2090 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2091 VamsasStMenu.removeAll();
2092 VamsasStMenu.setVisible(false);
2097 // Not interested in the content. Just hide ourselves.
2098 VamsasStMenu.setVisible(false);
2102 public void vamsasSave_actionPerformed(ActionEvent e)
2104 if (v_client != null)
2106 JalviewFileChooser chooser = new JalviewFileChooser(
2107 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
2108 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2110 { "Vamsas Document" }, "Vamsas Document");
2112 chooser.setFileView(new JalviewFileView());
2113 chooser.setDialogTitle(MessageManager.getString("label.save_vamsas_document_archive"));
2115 int value = chooser.showSaveDialog(this);
2117 if (value == JalviewFileChooser.APPROVE_OPTION)
2119 java.io.File choice = chooser.getSelectedFile();
2120 JPanel progpanel = addProgressPanel(MessageManager.formatMessage("label.saving_vamsas_doc", new String[]{choice.getName()}));
2121 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2122 String warnmsg = null;
2123 String warnttl = null;
2126 v_client.vclient.storeDocument(choice);
2129 warnttl = "Serious Problem saving Vamsas Document";
2130 warnmsg = ex.toString();
2131 jalview.bin.Cache.log.error("Error Whilst saving document to "
2134 } catch (Exception ex)
2136 warnttl = "Problem saving Vamsas Document.";
2137 warnmsg = ex.toString();
2138 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2142 removeProgressPanel(progpanel);
2143 if (warnmsg != null)
2145 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2147 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2153 JPanel vamUpdate = null;
2156 * hide vamsas user gui bits when a vamsas document event is being handled.
2159 * true to hide gui, false to reveal gui
2161 public void setVamsasUpdate(boolean b)
2163 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2164 + (b ? "in progress" : "finished"));
2166 if (vamUpdate != null)
2168 this.removeProgressPanel(vamUpdate);
2172 vamUpdate = this.addProgressPanel(MessageManager.getString("label.updating_vamsas_session"));
2174 vamsasStart.setVisible(!b);
2175 vamsasStop.setVisible(!b);
2176 vamsasSave.setVisible(!b);
2179 public JInternalFrame[] getAllFrames()
2181 return desktop.getAllFrames();
2185 * Checks the given url to see if it gives a response indicating that the user
2186 * should be informed of a new questionnaire.
2190 public void checkForQuestionnaire(String url)
2192 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2193 // javax.swing.SwingUtilities.invokeLater(jvq);
2194 new Thread(jvq).start();
2198 * Proxy class for JDesktopPane which optionally displays the current memory
2199 * usage and highlights the desktop area with a red bar if free memory runs
2204 public class MyDesktopPane extends JDesktopPane implements Runnable
2207 boolean showMemoryUsage = false;
2211 java.text.NumberFormat df;
2213 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2216 public MyDesktopPane(boolean showMemoryUsage)
2218 showMemoryUsage(showMemoryUsage);
2221 public void showMemoryUsage(boolean showMemoryUsage)
2223 this.showMemoryUsage = showMemoryUsage;
2224 if (showMemoryUsage)
2226 Thread worker = new Thread(this);
2231 public boolean isShowMemoryUsage()
2233 return showMemoryUsage;
2238 df = java.text.NumberFormat.getNumberInstance();
2239 df.setMaximumFractionDigits(2);
2240 runtime = Runtime.getRuntime();
2242 while (showMemoryUsage)
2246 maxMemory = runtime.maxMemory() / 1048576f;
2247 allocatedMemory = runtime.totalMemory() / 1048576f;
2248 freeMemory = runtime.freeMemory() / 1048576f;
2249 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2251 percentUsage = (totalFreeMemory / maxMemory) * 100;
2253 // if (percentUsage < 20)
2255 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2257 // instance.set.setBorder(border1);
2260 // sleep after showing usage
2262 } catch (Exception ex)
2264 ex.printStackTrace();
2269 public void paintComponent(Graphics g)
2271 if (showMemoryUsage && g != null && df != null)
2273 if (percentUsage < 20)
2275 g.setColor(Color.red);
2277 FontMetrics fm = g.getFontMetrics();
2280 g.drawString(MessageManager.formatMessage(
2281 "label.memory_stats",
2283 { df.format(totalFreeMemory), df.format(maxMemory),
2284 df.format(percentUsage) }), 10,
2285 getHeight() - fm.getHeight());
2292 * fixes stacking order after a modal dialog to ensure windows that should be
2293 * on top actually are
2295 public void relayerWindows()
2300 protected JMenuItem groovyShell;
2302 public void doGroovyCheck()
2304 if (jalview.bin.Cache.groovyJarsPresent())
2306 groovyShell = new JMenuItem();
2307 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2308 groovyShell.addActionListener(new ActionListener()
2310 public void actionPerformed(ActionEvent e)
2312 groovyShell_actionPerformed(e);
2315 toolsMenu.add(groovyShell);
2316 groovyShell.setVisible(true);
2321 * Accessor method to quickly get all the AlignmentFrames loaded.
2323 public static AlignFrame[] getAlignframes()
2325 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2331 Vector avp = new Vector();
2335 for (int i = frames.length - 1; i > -1; i--)
2337 if (frames[i] instanceof AlignFrame)
2339 AlignFrame af = (AlignFrame) frames[i];
2343 } catch (Exception ex)
2345 ex.printStackTrace();
2347 if (avp.size() == 0)
2351 AlignFrame afs[] = new AlignFrame[avp.size()];
2352 for (int i = 0, j = avp.size(); i < j; i++)
2354 afs[i] = (AlignFrame) avp.elementAt(i);
2360 public GStructureViewer[] getJmols()
2362 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2368 Vector avp = new Vector();
2372 for (int i = frames.length - 1; i > -1; i--)
2374 if (frames[i] instanceof AppJmol)
2376 GStructureViewer af = (GStructureViewer) frames[i];
2380 } catch (Exception ex)
2382 ex.printStackTrace();
2384 if (avp.size() == 0)
2388 GStructureViewer afs[] = new GStructureViewer[avp.size()];
2389 for (int i = 0, j = avp.size(); i < j; i++)
2391 afs[i] = (GStructureViewer) avp.elementAt(i);
2398 * Add Groovy Support to Jalview
2400 public void groovyShell_actionPerformed(ActionEvent e)
2402 // use reflection to avoid creating compilation dependency.
2403 if (!jalview.bin.Cache.groovyJarsPresent())
2405 throw new Error(MessageManager.getString("error.implementation_error_cannot_create_groovyshell"));
2409 Class gcClass = Desktop.class.getClassLoader().loadClass(
2410 "groovy.ui.Console");
2411 Constructor gccons = gcClass.getConstructor(null);
2412 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2414 { String.class, Object.class });
2415 java.lang.reflect.Method run = gcClass.getMethod("run", null);
2416 Object gc = gccons.newInstance(null);
2417 setvar.invoke(gc, new Object[]
2418 { "Jalview", this });
2419 run.invoke(gc, null);
2420 } catch (Exception ex)
2422 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2424 .showInternalMessageDialog(
2427 MessageManager.getString("label.couldnt_create_groovy_shell"),
2428 MessageManager.getString("label.groovy_support_failed"),
2429 JOptionPane.ERROR_MESSAGE);
2434 * Progress bars managed by the IProgressIndicator method.
2436 private Hashtable<Long, JPanel> progressBars;
2438 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2443 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2445 public void setProgressBar(String message, long id)
2447 if (progressBars == null)
2449 progressBars = new Hashtable<Long, JPanel>();
2450 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2453 if (progressBars.get(new Long(id)) != null)
2455 JPanel progressPanel = progressBars.remove(new Long(id));
2456 if (progressBarHandlers.contains(new Long(id)))
2458 progressBarHandlers.remove(new Long(id));
2460 removeProgressPanel(progressPanel);
2464 progressBars.put(new Long(id), addProgressPanel(message));
2471 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2472 * jalview.gui.IProgressIndicatorHandler)
2474 public void registerHandler(final long id,
2475 final IProgressIndicatorHandler handler)
2477 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
2479 throw new Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
2481 progressBarHandlers.put(new Long(id), handler);
2482 final JPanel progressPanel = progressBars.get(new Long(id));
2483 if (handler.canCancel())
2485 JButton cancel = new JButton(
2486 MessageManager.getString("action.cancel"));
2487 final IProgressIndicator us = this;
2488 cancel.addActionListener(new ActionListener()
2491 public void actionPerformed(ActionEvent e)
2493 handler.cancelActivity(id);
2494 us.setProgressBar(MessageManager.formatMessage("label.cancelled_params", new String[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
2497 progressPanel.add(cancel, BorderLayout.EAST);
2503 * @return true if any progress bars are still active
2506 public boolean operationInProgress()
2508 if (progressBars != null && progressBars.size() > 0)
2516 * This will return the first AlignFrame viewing AlignViewport av. It will
2517 * break if there are more than one AlignFrames viewing a particular av. This
2520 * @return alignFrame for av
2522 public static AlignFrame getAlignFrameFor(AlignViewport av)
2524 if (desktop != null)
2526 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
2527 for (int panel = 0; aps != null && panel < aps.length; panel++)
2529 if (aps[panel] != null && aps[panel].av == av)
2531 return aps[panel].alignFrame;
2538 public VamsasApplication getVamsasApplication()
2545 * flag set if jalview GUI is being operated programmatically
2547 private boolean inBatchMode = false;
2550 * check if jalview GUI is being operated programmatically
2552 * @return inBatchMode
2554 public boolean isInBatchMode()
2560 * set flag if jalview GUI is being operated programmatically
2562 * @param inBatchMode
2564 public void setInBatchMode(boolean inBatchMode)
2566 this.inBatchMode = inBatchMode;
2569 public void startServiceDiscovery()
2571 startServiceDiscovery(false);
2574 public void startServiceDiscovery(boolean blocking)
2576 boolean alive = true;
2577 Thread t0 = null, t1 = null, t2 = null;
2578 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2581 // todo: changesupport handlers need to be transferred
2582 if (discoverer == null)
2584 discoverer = new jalview.ws.jws1.Discoverer();
2585 // register PCS handler for desktop.
2586 discoverer.addPropertyChangeListener(changeSupport);
2588 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2589 // until we phase out completely
2590 (t0 = new Thread(discoverer)).start();
2593 // ENFIN services are EOLed as of Jalview 2.8.1 release
2598 if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
2600 // EnfinEnvision web service menu entries are rebuild every time the
2601 // menu is shown, so no changeSupport events are needed.
2602 jalview.ws.EnfinEnvision2OneWay.getInstance();
2603 (t1 = new Thread(jalview.ws.EnfinEnvision2OneWay.getInstance()))
2606 } catch (Exception e)
2609 .info("Exception when trying to launch Envision2 workflow discovery.",
2611 Cache.log.info(e.getStackTrace());
2615 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2617 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2619 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2621 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2627 // TODO: do rest service discovery
2636 } catch (Exception e)
2639 alive = (t1 != null && t1.isAlive())
2640 || (t2 != null && t2.isAlive())
2641 || (t3 != null && t3.isAlive())
2642 || (t0 != null && t0.isAlive());
2648 * called to check if the service discovery process completed successfully.
2652 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2654 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2656 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2657 .getErrorMessages();
2660 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2662 if (serviceChangedDialog == null)
2664 // only run if we aren't already displaying one of these.
2665 addDialogThread(serviceChangedDialog = new Runnable()
2671 * JalviewDialog jd =new JalviewDialog() {
2673 * @Override protected void cancelPressed() { // TODO
2674 * Auto-generated method stub
2676 * }@Override protected void okPressed() { // TODO
2677 * Auto-generated method stub
2679 * }@Override protected void raiseClosed() { // TODO
2680 * Auto-generated method stub
2682 * } }; jd.initDialogFrame(new
2683 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2684 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2685 * + " or mis-configured HTTP proxy settings.<br/>" +
2686 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2688 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2689 * ), true, true, "Web Service Configuration Problem", 450,
2692 * jd.waitForInput();
2698 "<html><table width=\"450\"><tr><td>"
2700 + "</td></tr></table>"
2701 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2702 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2703 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2704 + " Tools->Preferences dialog box to change them.</p></html>"),
2705 "Web Service Configuration Problem",
2706 JOptionPane.DEFAULT_OPTION,
2707 JOptionPane.ERROR_MESSAGE);
2708 serviceChangedDialog = null;
2717 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2724 private Runnable serviceChangedDialog = null;
2727 * start a thread to open a URL in the configured browser. Pops up a warning
2728 * dialog to the user if there is an exception when calling out to the browser
2733 public static void showUrl(final String url)
2735 showUrl(url, Desktop.instance);
2739 * Like showUrl but allows progress handler to be specified
2743 * (null) or object implementing IProgressIndicator
2745 public static void showUrl(final String url,
2746 final IProgressIndicator progress)
2748 new Thread(new Runnable()
2754 if (progress != null)
2756 progress.setProgressBar(MessageManager.formatMessage("status.opening_params", new String[]{url}), this.hashCode());
2758 jalview.util.BrowserLauncher.openURL(url);
2759 } catch (Exception ex)
2762 .showInternalMessageDialog(
2764 MessageManager.getString("label.web_browser_not_found_unix"),
2765 MessageManager.getString("label.web_browser_not_found"),
2766 JOptionPane.WARNING_MESSAGE);
2768 ex.printStackTrace();
2770 if (progress != null)
2772 progress.setProgressBar(null, this.hashCode());
2778 public static WsParamSetManager wsparamManager = null;
2780 public static ParamManager getUserParameterStore()
2782 if (wsparamManager == null)
2784 wsparamManager = new WsParamSetManager();
2786 return wsparamManager;
2790 * static hyperlink handler proxy method for use by Jalview's internal windows
2794 public static void hyperlinkUpdate(HyperlinkEvent e)
2796 if (e.getEventType() == EventType.ACTIVATED)
2801 url = e.getURL().toString();
2802 Desktop.showUrl(url);
2803 } catch (Exception x)
2807 if (Cache.log != null)
2809 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2813 System.err.println("Couldn't handle string " + url
2817 // ignore any exceptions due to dud links.
2824 * single thread that handles display of dialogs to user.
2826 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2829 * flag indicating if dialogExecutor should try to acquire a permit
2831 private volatile boolean dialogPause = true;
2836 private java.util.concurrent.Semaphore block = new Semaphore(0);
2839 * add another dialog thread to the queue
2843 public void addDialogThread(final Runnable prompter)
2845 dialogExecutor.submit(new Runnable()
2854 } catch (InterruptedException x)
2859 if (instance == null)
2865 SwingUtilities.invokeAndWait(prompter);
2866 } catch (Exception q)
2868 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2874 public void startDialogQueue()
2876 // set the flag so we don't pause waiting for another permit and semaphore
2877 // the current task to begin
2878 dialogPause = false;
2882 protected void snapShotWindow_actionPerformed(ActionEvent e)
2886 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
2887 "View of Desktop", getWidth(), getHeight(), of = new File(
2888 "Jalview_snapshot" + System.currentTimeMillis()
2889 + ".eps"), "View of desktop");
2891 paintAll(im.getGraphics());
2893 } catch (Exception q)
2895 Cache.log.error("Couldn't write snapshot to "+of.getAbsolutePath(),q);
2898 Cache.log.info("Successfully written snapshot to file "+of.getAbsolutePath());