2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
24 import java.awt.datatransfer.*;
25 import java.awt.dnd.*;
26 import java.awt.event.*;
27 import java.io.BufferedInputStream;
28 import java.io.BufferedOutputStream;
30 import java.io.FileOutputStream;
31 import java.io.InputStream;
32 import java.lang.reflect.Constructor;
34 import java.net.URLConnection;
35 import java.nio.channels.ReadableByteChannel;
39 import javax.swing.event.MenuEvent;
40 import javax.swing.event.MenuListener;
48 public class Desktop extends jalview.jbgui.GDesktop implements
49 DropTargetListener, ClipboardOwner, IProgressIndicator
52 public static Desktop instance;
54 // Need to decide if the Memory Usage is to be included in
55 // Next release or not.
56 public static MyDesktopPane desktop;
58 // public static JDesktopPane desktop;
60 static int openFrameCount = 0;
62 static final int xOffset = 30;
64 static final int yOffset = 30;
66 public static jalview.ws.Discoverer discoverer;
68 public static Object[] jalviewClipboard;
70 public static boolean internalCopy = false;
72 static int fileLoadingCount = 0;
73 class MyDesktopManager implements DesktopManager {
75 private DesktopManager delegate;
77 public MyDesktopManager(DesktopManager delegate) {
78 this.delegate = delegate;
81 public void activateFrame(JInternalFrame f) {
83 delegate.activateFrame(f);
84 } catch (NullPointerException npe) {
85 Point p = getMousePosition();
86 instance.showPasteMenu(p.x,p.y);
90 public void beginDraggingFrame(JComponent f) {
91 delegate.beginDraggingFrame(f);
94 public void beginResizingFrame(JComponent f, int direction) {
95 delegate.beginResizingFrame(f, direction);
98 public void closeFrame(JInternalFrame f) {
99 delegate.closeFrame(f);
102 public void deactivateFrame(JInternalFrame f) {
103 delegate.deactivateFrame(f);
106 public void deiconifyFrame(JInternalFrame f) {
107 delegate.deiconifyFrame(f);
110 public void dragFrame(JComponent f, int newX, int newY) {
111 delegate.dragFrame(f, newX, newY);
114 public void endDraggingFrame(JComponent f) {
115 delegate.endDraggingFrame(f);
118 public void endResizingFrame(JComponent f) {
119 delegate.endResizingFrame(f);
122 public void iconifyFrame(JInternalFrame f) {
123 delegate.iconifyFrame(f);
126 public void maximizeFrame(JInternalFrame f) {
127 delegate.maximizeFrame(f);
130 public void minimizeFrame(JInternalFrame f) {
131 delegate.minimizeFrame(f);
134 public void openFrame(JInternalFrame f) {
135 delegate.openFrame(f);
138 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
140 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
143 public void setBoundsForFrame(JComponent f, int newX, int newY,
144 int newWidth, int newHeight) {
145 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
148 // All other methods, simply delegate
152 * Creates a new Desktop object.
157 * A note to implementors. It is ESSENTIAL that any activities that might
158 * block are spawned off as threads rather than waited for during this
162 doVamsasClientCheck();
165 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
166 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
167 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
169 boolean showjconsole = jalview.bin.Cache.getDefault(
170 "SHOW_JAVA_CONSOLE", false);
171 desktop = new MyDesktopPane(selmemusage);
172 showMemusage.setSelected(selmemusage);
173 desktop.setBackground(Color.white);
174 getContentPane().setLayout(new BorderLayout());
175 getContentPane().add(desktop, BorderLayout.CENTER);
176 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
178 // This line prevents Windows Look&Feel resizing all new windows to maximum
179 // if previous window was maximised
180 desktop.setDesktopManager(new MyDesktopManager(new DefaultDesktopManager()));
181 Rectangle dims = getLastKnownDimensions("");
188 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
189 setBounds((int) (screenSize.width - 900) / 2,
190 (int) (screenSize.height - 650) / 2, 900, 650);
192 jconsole = new Console(this, showjconsole);
193 // add essential build information
194 jconsole.setHeader("Jalview Desktop "
195 + jalview.bin.Cache.getProperty("VERSION") + "\n"
197 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
198 + "Java version: " + System.getProperty("java.version") + "\n"
199 + System.getProperty("os.arch") + " "
200 + System.getProperty("os.name") + " "
201 + System.getProperty("os.version"));
203 showConsole(showjconsole);
205 this.addWindowListener(new WindowAdapter()
207 public void windowClosing(WindowEvent evt)
213 this.addMouseListener(new MouseAdapter()
215 public void mousePressed(MouseEvent evt)
217 if (SwingUtilities.isRightMouseButton(evt))
219 showPasteMenu(evt.getX(), evt.getY());
224 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
225 // Spawn a thread that shows the splashscreen
226 SwingUtilities.invokeLater(new Runnable()
234 discoverer = new jalview.ws.Discoverer(); // Only gets started if gui is
236 // Thread off a new instance of the file chooser - this reduces the time it
237 // takes to open it later on.
238 new Thread(new Runnable()
242 Cache.log.debug("Filechooser init thread started.");
243 JalviewFileChooser chooser = new JalviewFileChooser(
244 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
245 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
246 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
247 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
248 Cache.log.debug("Filechooser init thread finished.");
254 * recover the last known dimensions for a jalview window
257 * - empty string is desktop, all other windows have unique prefix
258 * @return null or last known dimensions scaled to current geometry (if last
259 * window geom was known)
261 Rectangle getLastKnownDimensions(String windowName)
263 // TODO: lock aspect ratio for scaling desktop Bug #0058199
264 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
265 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
266 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
267 String width = jalview.bin.Cache.getProperty(windowName
269 String height = jalview.bin.Cache.getProperty(windowName
271 if ((x != null) && (y != null) && (width != null) && (height != null))
273 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
274 .parseInt(width), ih = Integer.parseInt(height);
275 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
277 // attempt #1 - try to cope with change in screen geometry - this
278 // version doesn't preserve original jv aspect ratio.
279 // take ratio of current screen size vs original screen size.
280 double sw = ((1f * screenSize.width) / (1f * Integer
281 .parseInt(jalview.bin.Cache
282 .getProperty("SCREENGEOMETRY_WIDTH"))));
283 double sh = ((1f * screenSize.height) / (1f * Integer
284 .parseInt(jalview.bin.Cache
285 .getProperty("SCREENGEOMETRY_HEIGHT"))));
286 // rescale the bounds depending upon the current screen geometry.
287 ix = (int) (ix * sw);
288 iw = (int) (iw * sw);
289 iy = (int) (iy * sh);
290 ih = (int) (ih * sh);
291 jalview.bin.Cache.log.debug("Got last known dimensions for "
292 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
295 // return dimensions for new instance
296 return new Rectangle(ix, iy, iw, ih);
301 private void doVamsasClientCheck()
303 if (jalview.bin.Cache.vamsasJarsPresent())
305 setupVamsasDisconnectedGui();
306 VamsasMenu.setVisible(true);
307 final Desktop us = this;
308 VamsasMenu.addMenuListener(new MenuListener()
310 // this listener remembers when the menu was first selected, and
311 // doesn't rebuild the session list until it has been cleared and
313 boolean refresh = true;
315 public void menuCanceled(MenuEvent e)
320 public void menuDeselected(MenuEvent e)
325 public void menuSelected(MenuEvent e)
329 us.buildVamsasStMenu();
334 vamsasStart.setVisible(true);
338 void showPasteMenu(int x, int y)
340 JPopupMenu popup = new JPopupMenu();
341 JMenuItem item = new JMenuItem("Paste To New Window");
342 item.addActionListener(new ActionListener()
344 public void actionPerformed(ActionEvent evt)
351 popup.show(this, x, y);
358 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
359 Transferable contents = c.getContents(this);
361 if (contents != null)
363 String file = (String) contents
364 .getTransferData(DataFlavor.stringFlavor);
366 String format = new IdentifyFile().Identify(file,
367 FormatAdapter.PASTE);
369 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
372 } catch (Exception ex)
375 .println("Unable to paste alignment from system clipboard:\n"
381 * Adds and opens the given frame to the desktop
392 public static synchronized void addInternalFrame(
393 final JInternalFrame frame, String title, int w, int h)
395 addInternalFrame(frame, title, w, h, true);
412 public static synchronized void addInternalFrame(
413 final JInternalFrame frame, String title, int w, int h,
417 // TODO: allow callers to determine X and Y position of frame (eg. via
419 // TODO: consider fixing method to update entries in the window submenu with
420 // the current window title
422 frame.setTitle(title);
423 if (frame.getWidth() < 1 || frame.getHeight() < 1)
427 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
428 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
429 // IF JALVIEW IS RUNNING HEADLESS
430 // ///////////////////////////////////////////////
431 if (System.getProperty("java.awt.headless") != null
432 && System.getProperty("java.awt.headless").equals("true"))
439 frame.setVisible(true);
440 frame.setClosable(true);
441 frame.setResizable(resizable);
442 frame.setMaximizable(resizable);
443 frame.setIconifiable(resizable);
444 frame.setFrameIcon(null);
446 if (frame.getX() < 1 && frame.getY() < 1)
448 frame.setLocation(xOffset * openFrameCount, yOffset
449 * ((openFrameCount - 1) % 10) + yOffset);
452 final JMenuItem menuItem = new JMenuItem(title);
454 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
456 public void internalFrameActivated(
457 javax.swing.event.InternalFrameEvent evt)
459 JInternalFrame itf = desktop.getSelectedFrame();
467 public void internalFrameClosed(
468 javax.swing.event.InternalFrameEvent evt)
470 PaintRefresher.RemoveComponent(frame);
472 windowMenu.remove(menuItem);
473 JInternalFrame itf = desktop.getSelectedFrame();
482 menuItem.addActionListener(new ActionListener()
484 public void actionPerformed(ActionEvent e)
488 frame.setSelected(true);
489 frame.setIcon(false);
490 } catch (java.beans.PropertyVetoException ex)
497 windowMenu.add(menuItem);
503 frame.setSelected(true);
504 frame.requestFocus();
505 } catch (java.beans.PropertyVetoException ve)
510 public void lostOwnership(Clipboard clipboard, Transferable contents)
514 Desktop.jalviewClipboard = null;
517 internalCopy = false;
520 public void dragEnter(DropTargetDragEvent evt)
524 public void dragExit(DropTargetEvent evt)
528 public void dragOver(DropTargetDragEvent evt)
532 public void dropActionChanged(DropTargetDragEvent evt)
542 public void drop(DropTargetDropEvent evt)
544 Transferable t = evt.getTransferable();
545 java.util.List files = null;
546 java.util.List protocols = null;
550 DataFlavor uriListFlavor = new DataFlavor(
551 "text/uri-list;class=java.lang.String");
552 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
554 // Works on Windows and MacOSX
555 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
556 files = (java.util.List) t
557 .getTransferData(DataFlavor.javaFileListFlavor);
559 else if (t.isDataFlavorSupported(uriListFlavor))
561 // This is used by Unix drag system
562 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
563 String data = (String) t.getTransferData(uriListFlavor);
564 files = new java.util.ArrayList(1);
565 protocols = new java.util.ArrayList(1);
566 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
567 data, "\r\n"); st.hasMoreTokens();)
569 String s = st.nextToken();
570 if (s.startsWith("#"))
572 // the line is a comment (as per the RFC 2483)
575 java.net.URI uri = new java.net.URI(s);
576 if (uri.getScheme().toLowerCase().startsWith("http"))
578 protocols.add(FormatAdapter.URL);
579 files.add(uri.toString());
583 // otherwise preserve old behaviour: catch all for file objects
584 java.io.File file = new java.io.File(uri);
585 protocols.add(FormatAdapter.FILE);
586 files.add(file.toString());
590 } catch (Exception e)
598 for (int i = 0; i < files.size(); i++)
600 String file = files.get(i).toString();
601 String protocol = (protocols == null) ? FormatAdapter.FILE
602 : (String) protocols.get(i);
603 String format = null;
605 if (file.endsWith(".jar"))
612 format = new IdentifyFile().Identify(file, protocol);
615 new FileLoader().LoadFile(file, protocol, format);
618 } catch (Exception ex)
630 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
632 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
633 .getProperty("LAST_DIRECTORY"),
634 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
635 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
636 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
638 chooser.setFileView(new JalviewFileView());
639 chooser.setDialogTitle("Open local file");
640 chooser.setToolTipText("Open");
642 int value = chooser.showOpenDialog(this);
644 if (value == JalviewFileChooser.APPROVE_OPTION)
646 String choice = chooser.getSelectedFile().getPath();
647 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
648 .getSelectedFile().getParent());
650 String format = null;
651 if (chooser.getSelectedFormat().equals("Jalview"))
657 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
660 if (viewport != null)
662 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
667 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
678 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
680 // This construct allows us to have a wider textfield
682 JLabel label = new JLabel("Enter URL of Input File");
683 final JComboBox history = new JComboBox();
685 JPanel panel = new JPanel(new GridLayout(2, 1));
688 history.setPreferredSize(new Dimension(400, 20));
689 history.setEditable(true);
690 history.addItem("http://www.");
692 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
696 if (historyItems != null)
698 st = new StringTokenizer(historyItems, "\t");
700 while (st.hasMoreTokens())
702 history.addItem(st.nextElement());
706 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
707 "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
709 if (reply != JOptionPane.OK_OPTION)
714 String url = history.getSelectedItem().toString();
716 if (url.toLowerCase().endsWith(".jar"))
718 if (viewport != null)
720 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
725 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
730 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
732 if (format.equals("URL NOT FOUND"))
734 JOptionPane.showInternalMessageDialog(Desktop.desktop,
735 "Couldn't locate " + url, "URL not found",
736 JOptionPane.WARNING_MESSAGE);
741 if (viewport != null)
743 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
747 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
758 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
760 CutAndPasteTransfer cap = new CutAndPasteTransfer();
761 cap.setForInput(viewport);
762 Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
770 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
772 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
773 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
775 storeLastKnownDimensions("", new Rectangle(getBounds().x,
776 getBounds().y, getWidth(), getHeight()));
778 if (jconsole != null)
780 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
781 jconsole.stopConsole();
786 private void storeLastKnownDimensions(String string, Rectangle jc)
788 jalview.bin.Cache.log.debug("Storing last known dimensions for "
789 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
790 + " height:" + jc.height);
792 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
793 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
794 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
795 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
804 public void aboutMenuItem_actionPerformed(ActionEvent e)
806 StringBuffer message = new StringBuffer("Jalview version "
807 + jalview.bin.Cache.getProperty("VERSION") + "; last updated: "
808 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
810 if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
811 jalview.bin.Cache.getProperty("VERSION")))
814 .append("\n\n!! Jalview version "
815 + jalview.bin.Cache.getProperty("LATEST_VERSION")
816 + " is available for download from http://www.jalview.org !!\n");
819 // TODO: update this text for each release or centrally store it for lite
822 .append("\nAuthors: Andrew Waterhouse, Jim Procter, Michele Clamp, James Cuff, Steve Searle,\n David Martin & Geoff Barton."
823 + "\nDevelopment managed by The Barton Group, University of Dundee, Scotland, UK.\n"
824 + "\nFor help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list\n"
825 + "\nIf you use Jalview, please cite:"
826 + "\nWaterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
827 + "\nJalview Version 2 - a multiple sequence alignment editor and analysis workbench"
828 + "\nBioinformatics doi: 10.1093/bioinformatics/btp033");
829 JOptionPane.showInternalMessageDialog(Desktop.desktop,
831 message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
840 public void documentationMenuItem_actionPerformed(ActionEvent e)
844 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
845 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
846 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
848 javax.help.HelpBroker hb = hs.createHelpBroker();
849 hb.setCurrentID("home");
850 hb.setDisplayed(true);
851 } catch (Exception ex)
856 public void closeAll_actionPerformed(ActionEvent e)
858 JInternalFrame[] frames = desktop.getAllFrames();
859 for (int i = 0; i < frames.length; i++)
863 frames[i].setClosed(true);
864 } catch (java.beans.PropertyVetoException ex)
868 System.out.println("ALL CLOSED");
869 if (v_client != null)
871 // TODO clear binding to vamsas document objects on close_all
876 public void raiseRelated_actionPerformed(ActionEvent e)
878 reorderAssociatedWindows(false, false);
881 public void minimizeAssociated_actionPerformed(ActionEvent e)
883 reorderAssociatedWindows(true, false);
886 void closeAssociatedWindows()
888 reorderAssociatedWindows(false, true);
894 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
897 protected void garbageCollect_actionPerformed(ActionEvent e)
899 // We simply collect the garbage
900 jalview.bin.Cache.log.debug("Collecting garbage...");
902 jalview.bin.Cache.log.debug("Finished garbage collection.");
909 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
912 protected void showMemusage_actionPerformed(ActionEvent e)
914 desktop.showMemoryUsage(showMemusage.isSelected());
921 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
924 protected void showConsole_actionPerformed(ActionEvent e)
926 showConsole(showConsole.isSelected());
929 Console jconsole = null;
932 * control whether the java console is visible or not
936 void showConsole(boolean selected)
938 showConsole.setSelected(selected);
939 // TODO: decide if we should update properties file
940 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
942 jconsole.setVisible(selected);
945 void reorderAssociatedWindows(boolean minimize, boolean close)
947 JInternalFrame[] frames = desktop.getAllFrames();
948 if (frames == null || frames.length < 1)
953 AlignViewport source = null, target = null;
954 if (frames[0] instanceof AlignFrame)
956 source = ((AlignFrame) frames[0]).getCurrentView();
958 else if (frames[0] instanceof TreePanel)
960 source = ((TreePanel) frames[0]).getViewPort();
962 else if (frames[0] instanceof PCAPanel)
964 source = ((PCAPanel) frames[0]).av;
966 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
968 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
973 for (int i = 0; i < frames.length; i++)
976 if (frames[i] == null)
980 if (frames[i] instanceof AlignFrame)
982 target = ((AlignFrame) frames[i]).getCurrentView();
984 else if (frames[i] instanceof TreePanel)
986 target = ((TreePanel) frames[i]).getViewPort();
988 else if (frames[i] instanceof PCAPanel)
990 target = ((PCAPanel) frames[i]).av;
992 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
994 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
997 if (source == target)
1003 frames[i].setClosed(true);
1007 frames[i].setIcon(minimize);
1010 frames[i].toFront();
1014 } catch (java.beans.PropertyVetoException ex)
1028 protected void preferences_actionPerformed(ActionEvent e)
1039 public void saveState_actionPerformed(ActionEvent e)
1041 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1042 .getProperty("LAST_DIRECTORY"), new String[]
1043 { "jar" }, new String[]
1044 { "Jalview Project" }, "Jalview Project");
1046 chooser.setFileView(new JalviewFileView());
1047 chooser.setDialogTitle("Save State");
1049 int value = chooser.showSaveDialog(this);
1051 if (value == JalviewFileChooser.APPROVE_OPTION)
1053 java.io.File choice = chooser.getSelectedFile();
1054 JProgressBar progpanel = addProgressPanel("Saving jalview project "
1055 + choice.getName());
1056 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1057 // TODO catch and handle errors for savestate
1058 new Jalview2XML().SaveState(choice);
1059 removeProgressPanel(progpanel);
1070 public void loadState_actionPerformed(ActionEvent e)
1072 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1073 .getProperty("LAST_DIRECTORY"), new String[]
1074 { "jar" }, new String[]
1075 { "Jalview Project" }, "Jalview Project");
1076 chooser.setFileView(new JalviewFileView());
1077 chooser.setDialogTitle("Restore state");
1079 int value = chooser.showOpenDialog(this);
1081 if (value == JalviewFileChooser.APPROVE_OPTION)
1083 String choice = chooser.getSelectedFile().getAbsolutePath();
1084 setProgressBar("loading jalview project "
1085 + chooser.getSelectedFile().getName(), choice.hashCode());
1086 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1087 .getSelectedFile().getParent());
1088 new Jalview2XML().LoadJalviewAlign(choice);
1089 setProgressBar(null, choice.hashCode());
1093 public void inputSequence_actionPerformed(ActionEvent e)
1095 new SequenceFetcher(this);
1098 JPanel progressPanel;
1100 public void startLoading(final String fileName)
1102 if (fileLoadingCount == 0)
1104 addProgressPanel("Loading File: " + fileName + " ");
1110 private JProgressBar addProgressPanel(String string)
1112 if (progressPanel == null)
1114 progressPanel = new JPanel(new BorderLayout());
1115 totalProgressCount = 0;
1117 JProgressBar progressBar = new JProgressBar();
1118 progressBar.setIndeterminate(true);
1120 progressPanel.add(new JLabel(string), BorderLayout.WEST);
1122 progressPanel.add(progressBar, BorderLayout.CENTER);
1124 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1125 totalProgressCount++;
1130 int totalProgressCount = 0;
1132 private void removeProgressPanel(JProgressBar progbar)
1134 if (progressPanel != null)
1136 progressPanel.remove(progbar);
1137 if (--totalProgressCount < 1)
1139 this.getContentPane().remove(progressPanel);
1140 progressPanel = null;
1146 public void stopLoading()
1149 if (fileLoadingCount < 1)
1151 if (progressPanel != null)
1153 this.getContentPane().remove(progressPanel);
1154 progressPanel = null;
1156 fileLoadingCount = 0;
1161 public static int getViewCount(String viewId)
1163 AlignViewport[] aps = getViewports(viewId);
1164 return (aps == null) ? 0 : aps.length;
1170 * @return all AlignmentPanels concerning the viewId sequence set
1172 public static AlignmentPanel[] getAlignmentPanels(String viewId)
1175 if (Desktop.desktop == null)
1177 // no frames created and in headless mode
1178 // TODO: verify that frames are recoverable when in headless mode
1181 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1182 ArrayList aps = new ArrayList();
1183 for (int t = 0; t < frames.length; t++)
1185 if (frames[t] instanceof AlignFrame)
1187 AlignFrame af = (AlignFrame) frames[t];
1188 for (int a = 0; a < af.alignPanels.size(); a++)
1191 .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
1192 .getSequenceSetId()))
1194 aps.add(af.alignPanels.elementAt(a));
1199 if (aps.size() == 0)
1203 AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
1204 for (int t = 0; t < vap.length; t++)
1206 vap[t] = (AlignmentPanel) aps.get(t);
1212 * get all the viewports on an alignment.
1214 * @param sequenceSetId
1215 * unique alignment id
1216 * @return all viewports on the alignment bound to sequenceSetId
1218 public static AlignViewport[] getViewports(String sequenceSetId)
1220 Vector viewp = new Vector();
1221 if (desktop != null)
1223 javax.swing.JInternalFrame[] frames = instance.getAllFrames();
1225 for (int t = 0; t < frames.length; t++)
1227 if (frames[t] instanceof AlignFrame)
1229 AlignFrame afr = ((AlignFrame) frames[t]);
1230 if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1232 if (afr.alignPanels != null)
1234 for (int a = 0; a < afr.alignPanels.size(); a++)
1236 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1237 .elementAt(a)).av.getSequenceSetId()))
1239 viewp.addElement(((AlignmentPanel) afr.alignPanels
1246 viewp.addElement(((AlignFrame) frames[t]).getViewport());
1251 if (viewp.size() > 0)
1253 AlignViewport[] vp = new AlignViewport[viewp.size()];
1261 public void explodeViews(AlignFrame af)
1263 int size = af.alignPanels.size();
1269 for (int i = 0; i < size; i++)
1271 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1272 AlignFrame newaf = new AlignFrame(ap);
1273 if (ap.av.explodedPosition != null
1274 && !ap.av.explodedPosition.equals(af.getBounds()))
1276 newaf.setBounds(ap.av.explodedPosition);
1279 ap.av.gatherViewsHere = false;
1281 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1282 AlignFrame.DEFAULT_HEIGHT);
1285 af.alignPanels.clear();
1286 af.closeMenuItem_actionPerformed(true);
1290 public void gatherViews(AlignFrame source)
1292 source.viewport.gatherViewsHere = true;
1293 source.viewport.explodedPosition = source.getBounds();
1294 JInternalFrame[] frames = desktop.getAllFrames();
1295 String viewId = source.viewport.sequenceSetID;
1297 for (int t = 0; t < frames.length; t++)
1299 if (frames[t] instanceof AlignFrame && frames[t] != source)
1301 AlignFrame af = (AlignFrame) frames[t];
1302 boolean gatherThis = false;
1303 for (int a = 0; a < af.alignPanels.size(); a++)
1305 AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1306 if (viewId.equals(ap.av.getSequenceSetId()))
1309 ap.av.gatherViewsHere = false;
1310 ap.av.explodedPosition = af.getBounds();
1311 source.addAlignmentPanel(ap, false);
1317 af.alignPanels.clear();
1318 af.closeMenuItem_actionPerformed(true);
1325 jalview.gui.VamsasApplication v_client = null;
1327 public void vamsasImport_actionPerformed(ActionEvent e)
1329 if (v_client == null)
1331 // Load and try to start a session.
1332 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1333 .getProperty("LAST_DIRECTORY"));
1335 chooser.setFileView(new JalviewFileView());
1336 chooser.setDialogTitle("Open a saved VAMSAS session");
1338 .setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1340 int value = chooser.showOpenDialog(this);
1342 if (value == JalviewFileChooser.APPROVE_OPTION)
1344 String fle = chooser.getSelectedFile().toString();
1345 if (!vamsasImport(chooser.getSelectedFile()))
1347 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1348 "Couldn't import '" + fle + "' as a new vamsas session.",
1349 "Vamsas Document Import Failed",
1350 JOptionPane.ERROR_MESSAGE);
1356 jalview.bin.Cache.log
1357 .error("Implementation error - load session from a running session is not supported.");
1362 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1365 * @return true if import was a success and a session was started.
1367 public boolean vamsasImport(URL url)
1369 // TODO: create progress bar
1370 if (v_client != null)
1373 jalview.bin.Cache.log
1374 .error("Implementation error - load session from a running session is not supported.");
1380 // copy the URL content to a temporary local file
1381 // TODO: be a bit cleverer here with nio (?!)
1382 File file = File.createTempFile("vdocfromurl", ".vdj");
1383 FileOutputStream fos = new FileOutputStream(file);
1384 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1385 byte[] buffer = new byte[2048];
1387 while ((ln = bis.read(buffer)) > -1)
1389 fos.write(buffer, 0, ln);
1393 v_client = new jalview.gui.VamsasApplication(this, file, url
1395 } catch (Exception ex)
1397 jalview.bin.Cache.log.error(
1398 "Failed to create new vamsas session from contents of URL "
1402 setupVamsasConnectedGui();
1403 v_client.initial_update(); // TODO: thread ?
1404 return v_client.inSession();
1408 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1411 * @return true if import was a success and a session was started.
1413 public boolean vamsasImport(File file)
1415 if (v_client != null)
1418 jalview.bin.Cache.log
1419 .error("Implementation error - load session from a running session is not supported.");
1423 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1427 v_client = new jalview.gui.VamsasApplication(this, file, null);
1428 } catch (Exception ex)
1430 setProgressBar("Importing VAMSAS session from " + file.getName(),
1432 jalview.bin.Cache.log.error(
1433 "New vamsas session from existing session file failed:", ex);
1436 setupVamsasConnectedGui();
1437 v_client.initial_update(); // TODO: thread ?
1438 setProgressBar("Importing VAMSAS session from " + file.getName(), file
1440 return v_client.inSession();
1443 public boolean joinVamsasSession(String mysesid)
1445 if (v_client != null)
1448 "Trying to join a vamsas session when another is already connected.");
1450 if (mysesid == null)
1452 throw new Error("Invalid vamsas session id.");
1454 v_client = new VamsasApplication(this, mysesid);
1455 setupVamsasConnectedGui();
1456 v_client.initial_update();
1457 return (v_client.inSession());
1460 public void vamsasStart_actionPerformed(ActionEvent e)
1462 if (v_client == null)
1465 // we just start a default session for moment.
1467 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1468 * getProperty("LAST_DIRECTORY"));
1470 * chooser.setFileView(new JalviewFileView());
1471 * chooser.setDialogTitle("Load Vamsas file");
1472 * chooser.setToolTipText("Import");
1474 * int value = chooser.showOpenDialog(this);
1476 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1477 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1479 v_client = new VamsasApplication(this);
1480 setupVamsasConnectedGui();
1481 v_client.initial_update(); // TODO: thread ?
1485 // store current data in session.
1486 v_client.push_update(); // TODO: thread
1490 protected void setupVamsasConnectedGui()
1492 vamsasStart.setText("Session Update");
1493 vamsasSave.setVisible(true);
1494 vamsasStop.setVisible(true);
1495 vamsasImport.setVisible(false); // Document import to existing session is
1496 // not possible for vamsas-client-1.0.
1499 protected void setupVamsasDisconnectedGui()
1501 vamsasSave.setVisible(false);
1502 vamsasStop.setVisible(false);
1503 vamsasImport.setVisible(true);
1504 vamsasStart.setText("New Vamsas Session");
1507 public void vamsasStop_actionPerformed(ActionEvent e)
1509 if (v_client != null)
1511 v_client.end_session();
1513 setupVamsasDisconnectedGui();
1517 protected void buildVamsasStMenu()
1519 if (v_client == null)
1521 String[] sess = null;
1524 sess = VamsasApplication.getSessionList();
1525 } catch (Exception e)
1527 jalview.bin.Cache.log.warn(
1528 "Problem getting current sessions list.", e);
1533 jalview.bin.Cache.log.debug("Got current sessions list: "
1534 + sess.length + " entries.");
1535 VamsasStMenu.removeAll();
1536 for (int i = 0; i < sess.length; i++)
1538 JMenuItem sessit = new JMenuItem();
1539 sessit.setText(sess[i]);
1540 sessit.setToolTipText("Connect to session " + sess[i]);
1541 final Desktop dsktp = this;
1542 final String mysesid = sess[i];
1543 sessit.addActionListener(new ActionListener()
1546 public void actionPerformed(ActionEvent e)
1548 if (dsktp.v_client == null)
1550 Thread rthr = new Thread(new Runnable()
1555 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1556 dsktp.setupVamsasConnectedGui();
1557 dsktp.v_client.initial_update();
1565 VamsasStMenu.add(sessit);
1567 // don't show an empty menu.
1568 VamsasStMenu.setVisible(sess.length > 0);
1573 jalview.bin.Cache.log.debug("No current vamsas sessions.");
1574 VamsasStMenu.removeAll();
1575 VamsasStMenu.setVisible(false);
1580 // Not interested in the content. Just hide ourselves.
1581 VamsasStMenu.setVisible(false);
1585 public void vamsasSave_actionPerformed(ActionEvent e)
1587 if (v_client != null)
1589 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1590 .getProperty("LAST_DIRECTORY"), new String[]
1591 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1593 { "Vamsas Document" }, "Vamsas Document");
1595 chooser.setFileView(new JalviewFileView());
1596 chooser.setDialogTitle("Save Vamsas Document Archive");
1598 int value = chooser.showSaveDialog(this);
1600 if (value == JalviewFileChooser.APPROVE_OPTION)
1602 java.io.File choice = chooser.getSelectedFile();
1603 JProgressBar progpanel = addProgressPanel("Saving VAMSAS Document to "
1604 + choice.getName());
1605 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1606 String warnmsg = null;
1607 String warnttl = null;
1610 v_client.vclient.storeDocument(choice);
1613 warnttl = "Serious Problem saving Vamsas Document";
1614 warnmsg = ex.toString();
1615 jalview.bin.Cache.log.error("Error Whilst saving document to "
1618 } catch (Exception ex)
1620 warnttl = "Problem saving Vamsas Document.";
1621 warnmsg = ex.toString();
1622 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1626 removeProgressPanel(progpanel);
1627 if (warnmsg != null)
1629 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1631 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1637 JProgressBar vamUpdate = null;
1640 * hide vamsas user gui bits when a vamsas document event is being handled.
1643 * true to hide gui, false to reveal gui
1645 public void setVamsasUpdate(boolean b)
1647 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
1648 + (b ? "in progress" : "finished"));
1650 if (vamUpdate != null)
1652 this.removeProgressPanel(vamUpdate);
1656 vamUpdate = this.addProgressPanel("Updating vamsas session");
1658 vamsasStart.setVisible(!b);
1659 vamsasStop.setVisible(!b);
1660 vamsasSave.setVisible(!b);
1663 public JInternalFrame[] getAllFrames()
1665 return desktop.getAllFrames();
1669 * Checks the given url to see if it gives a response indicating that the user
1670 * should be informed of a new questionnaire.
1674 public void checkForQuestionnaire(String url)
1676 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
1677 // javax.swing.SwingUtilities.invokeLater(jvq);
1678 new Thread(jvq).start();
1682 * Proxy class for JDesktopPane which optionally displays the current memory
1683 * usage and highlights the desktop area with a red bar if free memory runs
1688 public class MyDesktopPane extends JDesktopPane implements Runnable
1691 boolean showMemoryUsage = false;
1695 java.text.NumberFormat df;
1697 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
1700 public MyDesktopPane(boolean showMemoryUsage)
1702 showMemoryUsage(showMemoryUsage);
1705 public void showMemoryUsage(boolean showMemoryUsage)
1707 this.showMemoryUsage = showMemoryUsage;
1708 if (showMemoryUsage)
1710 Thread worker = new Thread(this);
1715 public boolean isShowMemoryUsage()
1717 return showMemoryUsage;
1722 df = java.text.NumberFormat.getNumberInstance();
1723 df.setMaximumFractionDigits(2);
1724 runtime = Runtime.getRuntime();
1726 while (showMemoryUsage)
1730 maxMemory = runtime.maxMemory() / 1048576f;
1731 allocatedMemory = runtime.totalMemory() / 1048576f;
1732 freeMemory = runtime.freeMemory() / 1048576f;
1733 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
1735 percentUsage = (totalFreeMemory / maxMemory) * 100;
1737 // if (percentUsage < 20)
1739 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
1741 // instance.set.setBorder(border1);
1744 // sleep after showing usage
1746 } catch (Exception ex)
1748 ex.printStackTrace();
1753 public void paintComponent(Graphics g)
1755 if (showMemoryUsage && g != null)
1757 if (percentUsage < 20)
1758 g.setColor(Color.red);
1759 FontMetrics fm = g.getFontMetrics();
1762 g.drawString("Total Free Memory: " + df.format(totalFreeMemory)
1763 + "MB; Max Memory: " + df.format(maxMemory) + "MB; "
1764 + df.format(percentUsage) + "%", 10, getHeight()
1772 protected JMenuItem groovyShell;
1774 public void doGroovyCheck()
1776 if (jalview.bin.Cache.groovyJarsPresent())
1778 groovyShell = new JMenuItem();
1779 groovyShell.setText("Groovy Console...");
1780 groovyShell.addActionListener(new ActionListener()
1782 public void actionPerformed(ActionEvent e)
1784 groovyShell_actionPerformed(e);
1787 toolsMenu.add(groovyShell);
1788 groovyShell.setVisible(true);
1793 * Accessor method to quickly get all the AlignmentFrames loaded.
1795 public static AlignFrame[] getAlignframes()
1797 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1803 Vector avp = new Vector();
1807 for (int i = frames.length - 1; i > -1; i--)
1809 if (frames[i] instanceof AlignFrame)
1811 AlignFrame af = (AlignFrame) frames[i];
1815 } catch (Exception ex)
1817 ex.printStackTrace();
1819 if (avp.size() == 0)
1823 AlignFrame afs[] = new AlignFrame[avp.size()];
1824 for (int i = 0, j = avp.size(); i < j; i++)
1826 afs[i] = (AlignFrame) avp.elementAt(i);
1833 * Add Groovy Support to Jalview
1835 public void groovyShell_actionPerformed(ActionEvent e)
1837 // use reflection to avoid creating compilation dependency.
1838 if (!jalview.bin.Cache.groovyJarsPresent())
1841 "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
1845 Class gcClass = Desktop.class.getClassLoader().loadClass(
1846 "groovy.ui.Console");
1847 Constructor gccons = gcClass.getConstructor(null);
1848 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
1850 { String.class, Object.class });
1851 java.lang.reflect.Method run = gcClass.getMethod("run", null);
1852 Object gc = gccons.newInstance(null);
1853 setvar.invoke(gc, new Object[]
1854 { "Jalview", this });
1855 run.invoke(gc, null);
1856 } catch (Exception ex)
1858 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
1860 .showInternalMessageDialog(
1863 "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
1864 "Jalview Groovy Support Failed",
1865 JOptionPane.ERROR_MESSAGE);
1870 * Progress bars managed by the IProgressIndicator method.
1872 private Hashtable progressBars, progressBarHandlers;
1877 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
1879 public void setProgressBar(String message, long id)
1881 if (progressBars == null)
1883 progressBars = new Hashtable();
1884 progressBarHandlers = new Hashtable();
1887 if (progressBars.get(new Long(id)) != null)
1889 JProgressBar progressPanel = (JProgressBar) progressBars
1890 .remove(new Long(id));
1891 if (progressBarHandlers.contains(new Long(id)))
1893 progressBarHandlers.remove(new Long(id));
1895 removeProgressPanel(progressPanel);
1899 progressBars.put(new Long(id), addProgressPanel(message));
1906 * @see jalview.gui.IProgressIndicator#registerHandler(long,
1907 * jalview.gui.IProgressIndicatorHandler)
1909 public void registerHandler(final long id,
1910 final IProgressIndicatorHandler handler)
1912 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
1915 "call setProgressBar before registering the progress bar's handler.");
1917 progressBarHandlers.put(new Long(id), handler);
1918 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
1919 if (handler.canCancel())
1921 JButton cancel = new JButton("Cancel");
1922 final IProgressIndicator us = this;
1923 cancel.addActionListener(new ActionListener()
1926 public void actionPerformed(ActionEvent e)
1928 handler.cancelActivity(id);
1929 us.setProgressBar("Cancelled "
1930 + ((JLabel) progressPanel.getComponent(0)).getText(), id);
1933 progressPanel.add(cancel, BorderLayout.EAST);
1938 * This will return the first AlignFrame viewing AlignViewport av. It will
1939 * break if there are more than one AlignFrames viewing a particular av. This
1942 * @return alignFrame for av
1944 public static AlignFrame getAlignFrameFor(AlignViewport av)
1946 if (desktop != null)
1948 AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
1949 for (int panel = 0; aps != null && panel < aps.length; panel++)
1951 if (aps[panel] != null && aps[panel].av == av)
1953 return aps[panel].alignFrame;
1960 public VamsasApplication getVamsasApplication()