2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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 static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.FileLoader;
30 import jalview.io.FormatAdapter;
31 import jalview.io.IdentifyFile;
32 import jalview.io.JalviewFileChooser;
33 import jalview.io.JalviewFileView;
34 import jalview.jbgui.GSplitFrame;
35 import jalview.jbgui.GStructureViewer;
36 import jalview.structure.StructureSelectionManager;
37 import jalview.urls.IdOrgSettings;
38 import jalview.util.ImageMaker;
39 import jalview.util.MessageManager;
40 import jalview.util.Platform;
41 import jalview.util.UrlConstants;
42 import jalview.viewmodel.AlignmentViewport;
43 import jalview.ws.UrlDownloadClient;
44 import jalview.ws.params.ParamManager;
46 import java.awt.BorderLayout;
47 import java.awt.Color;
48 import java.awt.Dimension;
49 import java.awt.FontMetrics;
50 import java.awt.Graphics;
51 import java.awt.GridLayout;
52 import java.awt.Point;
53 import java.awt.Rectangle;
54 import java.awt.Toolkit;
55 import java.awt.Window;
56 import java.awt.datatransfer.Clipboard;
57 import java.awt.datatransfer.ClipboardOwner;
58 import java.awt.datatransfer.DataFlavor;
59 import java.awt.datatransfer.Transferable;
60 import java.awt.dnd.DnDConstants;
61 import java.awt.dnd.DropTargetDragEvent;
62 import java.awt.dnd.DropTargetDropEvent;
63 import java.awt.dnd.DropTargetEvent;
64 import java.awt.dnd.DropTargetListener;
65 import java.awt.event.ActionEvent;
66 import java.awt.event.ActionListener;
67 import java.awt.event.FocusEvent;
68 import java.awt.event.FocusListener;
69 import java.awt.event.KeyEvent;
70 import java.awt.event.MouseAdapter;
71 import java.awt.event.MouseEvent;
72 import java.awt.event.WindowAdapter;
73 import java.awt.event.WindowEvent;
74 import java.beans.PropertyChangeEvent;
75 import java.beans.PropertyChangeListener;
76 import java.io.BufferedInputStream;
78 import java.io.FileOutputStream;
79 import java.io.IOException;
81 import java.util.ArrayList;
82 import java.util.Hashtable;
83 import java.util.List;
84 import java.util.ListIterator;
85 import java.util.StringTokenizer;
86 import java.util.Vector;
87 import java.util.concurrent.ExecutorService;
88 import java.util.concurrent.Executors;
89 import java.util.concurrent.Semaphore;
91 import javax.swing.AbstractAction;
92 import javax.swing.Box;
93 import javax.swing.BoxLayout;
94 import javax.swing.DefaultDesktopManager;
95 import javax.swing.DesktopManager;
96 import javax.swing.JButton;
97 import javax.swing.JCheckBox;
98 import javax.swing.JComboBox;
99 import javax.swing.JComponent;
100 import javax.swing.JDesktopPane;
101 import javax.swing.JFrame;
102 import javax.swing.JInternalFrame;
103 import javax.swing.JLabel;
104 import javax.swing.JMenuItem;
105 import javax.swing.JOptionPane;
106 import javax.swing.JPanel;
107 import javax.swing.JPopupMenu;
108 import javax.swing.JProgressBar;
109 import javax.swing.KeyStroke;
110 import javax.swing.SwingUtilities;
111 import javax.swing.event.HyperlinkEvent;
112 import javax.swing.event.HyperlinkEvent.EventType;
113 import javax.swing.event.InternalFrameAdapter;
114 import javax.swing.event.InternalFrameEvent;
115 import javax.swing.event.MenuEvent;
116 import javax.swing.event.MenuListener;
123 * @version $Revision: 1.155 $
125 public class Desktop extends jalview.jbgui.GDesktop implements
126 DropTargetListener, ClipboardOwner, IProgressIndicator,
127 jalview.api.StructureSelectionManagerProvider
130 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
133 * news reader - null if it was never started.
135 private BlogReader jvnews = null;
137 private File projectFile;
141 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
143 public void addJalviewPropertyChangeListener(
144 PropertyChangeListener listener)
146 changeSupport.addJalviewPropertyChangeListener(listener);
150 * @param propertyName
152 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
153 * java.beans.PropertyChangeListener)
155 public void addJalviewPropertyChangeListener(String propertyName,
156 PropertyChangeListener listener)
158 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
162 * @param propertyName
164 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
165 * java.beans.PropertyChangeListener)
167 public void removeJalviewPropertyChangeListener(String propertyName,
168 PropertyChangeListener listener)
170 changeSupport.removeJalviewPropertyChangeListener(propertyName,
174 /** Singleton Desktop instance */
175 public static Desktop instance;
177 public static MyDesktopPane desktop;
179 static int openFrameCount = 0;
181 static final int xOffset = 30;
183 static final int yOffset = 30;
185 public static jalview.ws.jws1.Discoverer discoverer;
187 public static Object[] jalviewClipboard;
189 public static boolean internalCopy = false;
191 static int fileLoadingCount = 0;
193 class MyDesktopManager implements DesktopManager
196 private DesktopManager delegate;
198 public MyDesktopManager(DesktopManager delegate)
200 this.delegate = delegate;
204 public void activateFrame(JInternalFrame f)
208 delegate.activateFrame(f);
209 } catch (NullPointerException npe)
211 Point p = getMousePosition();
212 instance.showPasteMenu(p.x, p.y);
217 public void beginDraggingFrame(JComponent f)
219 delegate.beginDraggingFrame(f);
223 public void beginResizingFrame(JComponent f, int direction)
225 delegate.beginResizingFrame(f, direction);
229 public void closeFrame(JInternalFrame f)
231 delegate.closeFrame(f);
235 public void deactivateFrame(JInternalFrame f)
237 delegate.deactivateFrame(f);
241 public void deiconifyFrame(JInternalFrame f)
243 delegate.deiconifyFrame(f);
247 public void dragFrame(JComponent f, int newX, int newY)
253 delegate.dragFrame(f, newX, newY);
257 public void endDraggingFrame(JComponent f)
259 delegate.endDraggingFrame(f);
263 public void endResizingFrame(JComponent f)
265 delegate.endResizingFrame(f);
269 public void iconifyFrame(JInternalFrame f)
271 delegate.iconifyFrame(f);
275 public void maximizeFrame(JInternalFrame f)
277 delegate.maximizeFrame(f);
281 public void minimizeFrame(JInternalFrame f)
283 delegate.minimizeFrame(f);
287 public void openFrame(JInternalFrame f)
289 delegate.openFrame(f);
293 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
300 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
304 public void setBoundsForFrame(JComponent f, int newX, int newY,
305 int newWidth, int newHeight)
307 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
310 // All other methods, simply delegate
315 * Creates a new Desktop object.
320 * A note to implementors. It is ESSENTIAL that any activities that might
321 * block are spawned off as threads rather than waited for during this
325 doVamsasClientCheck();
327 groovyShell = new JMenuItem();
328 groovyShell.setText(MessageManager.getString("label.groovy_console"));
329 groovyShell.addActionListener(new ActionListener()
332 public void actionPerformed(ActionEvent e)
334 groovyShell_actionPerformed();
337 toolsMenu.add(groovyShell);
338 groovyShell.setVisible(true);
340 doConfigureStructurePrefs();
341 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
342 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
345 boolean showjconsole = jalview.bin.Cache.getDefault(
346 "SHOW_JAVA_CONSOLE", false);
347 desktop = new MyDesktopPane(selmemusage);
348 if (Platform.isAMac())
350 desktop.setDoubleBuffered(false);
352 showMemusage.setSelected(selmemusage);
353 desktop.setBackground(Color.white);
354 getContentPane().setLayout(new BorderLayout());
355 // alternate config - have scrollbars - see notes in JAL-153
356 // JScrollPane sp = new JScrollPane();
357 // sp.getViewport().setView(desktop);
358 // getContentPane().add(sp, BorderLayout.CENTER);
359 getContentPane().add(desktop, BorderLayout.CENTER);
360 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
362 // This line prevents Windows Look&Feel resizing all new windows to maximum
363 // if previous window was maximised
364 desktop.setDesktopManager(new MyDesktopManager(
365 new DefaultDesktopManager()));
367 Rectangle dims = getLastKnownDimensions("");
374 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
375 setBounds((screenSize.width - 900) / 2,
376 (screenSize.height - 650) / 2, 900, 650);
378 jconsole = new Console(this, showjconsole);
379 // add essential build information
380 jconsole.setHeader("Jalview Version: "
381 + jalview.bin.Cache.getProperty("VERSION") + "\n"
382 + "Jalview Installation: "
383 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
384 + "\n" + "Build Date: "
385 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
386 + "Java version: " + System.getProperty("java.version") + "\n"
387 + System.getProperty("os.arch") + " "
388 + System.getProperty("os.name") + " "
389 + System.getProperty("os.version"));
391 showConsole(showjconsole);
393 showNews.setVisible(false);
395 getIdentifiersOrgData();
399 this.addWindowListener(new WindowAdapter()
402 public void windowClosing(WindowEvent evt)
409 this.addMouseListener(ma = new MouseAdapter()
412 public void mousePressed(MouseEvent evt)
414 if (evt.isPopupTrigger()) // Mac
416 showPasteMenu(evt.getX(), evt.getY());
421 public void mouseReleased(MouseEvent evt)
423 if (evt.isPopupTrigger()) // Windows
425 showPasteMenu(evt.getX(), evt.getY());
429 desktop.addMouseListener(ma);
431 this.addFocusListener(new FocusListener()
435 public void focusLost(FocusEvent e)
437 // TODO Auto-generated method stub
442 public void focusGained(FocusEvent e)
444 Cache.log.debug("Relaying windows after focus gain");
445 // make sure that we sort windows properly after we gain focus
446 instance.relayerWindows();
449 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
450 // Spawn a thread that shows the splashscreen
451 SwingUtilities.invokeLater(new Runnable()
461 // Thread off a new instance of the file chooser - this reduces the time it
462 // takes to open it later on.
463 new Thread(new Runnable()
468 Cache.log.debug("Filechooser init thread started.");
469 new JalviewFileChooser(
470 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
471 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
472 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
473 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
474 Cache.log.debug("Filechooser init thread finished.");
477 // Add the service change listener
478 changeSupport.addJalviewPropertyChangeListener("services",
479 new PropertyChangeListener()
483 public void propertyChange(PropertyChangeEvent evt)
485 Cache.log.debug("Firing service changed event for "
486 + evt.getNewValue());
487 JalviewServicesChanged(evt);
493 public void doConfigureStructurePrefs()
495 // configure services
496 StructureSelectionManager ssm = StructureSelectionManager
497 .getStructureSelectionManager(this);
498 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
500 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
501 Preferences.ADD_TEMPFACT_ANN, true));
502 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
503 Preferences.STRUCT_FROM_PDB, true));
504 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
505 Preferences.USE_RNAVIEW, true));
509 ssm.setAddTempFacAnnot(false);
510 ssm.setProcessSecondaryStructure(false);
511 ssm.setSecStructServices(false);
515 public void checkForNews()
517 final Desktop me = this;
518 // Thread off the news reader, in case there are connection problems.
519 addDialogThread(new Runnable()
524 Cache.log.debug("Starting news thread.");
526 jvnews = new BlogReader(me);
527 showNews.setVisible(true);
528 Cache.log.debug("Completed news thread.");
533 public void getIdentifiersOrgData()
535 // Thread off the identifiers fetcher
536 addDialogThread(new Runnable()
541 Cache.log.debug("Downloading data from identifiers.org");
542 UrlDownloadClient client = new UrlDownloadClient();
545 client.download(IdOrgSettings.getUrl(),
546 IdOrgSettings.getDownloadLocation());
547 } catch (IOException e)
549 Cache.log.debug("Exception downloading identifiers.org data"
557 protected void showNews_actionPerformed(ActionEvent e)
559 showNews(showNews.isSelected());
562 void showNews(boolean visible)
565 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
566 showNews.setSelected(visible);
567 if (visible && !jvnews.isVisible())
569 new Thread(new Runnable()
574 long now = System.currentTimeMillis();
575 Desktop.instance.setProgressBar(
576 MessageManager.getString("status.refreshing_news"), now);
577 jvnews.refreshNews();
578 Desktop.instance.setProgressBar(null, now);
587 * recover the last known dimensions for a jalview window
590 * - empty string is desktop, all other windows have unique prefix
591 * @return null or last known dimensions scaled to current geometry (if last
592 * window geom was known)
594 Rectangle getLastKnownDimensions(String windowName)
596 // TODO: lock aspect ratio for scaling desktop Bug #0058199
597 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
598 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
599 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
600 String width = jalview.bin.Cache.getProperty(windowName
602 String height = jalview.bin.Cache.getProperty(windowName
604 if ((x != null) && (y != null) && (width != null) && (height != null))
606 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
607 .parseInt(width), ih = Integer.parseInt(height);
608 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
610 // attempt #1 - try to cope with change in screen geometry - this
611 // version doesn't preserve original jv aspect ratio.
612 // take ratio of current screen size vs original screen size.
613 double sw = ((1f * screenSize.width) / (1f * Integer
614 .parseInt(jalview.bin.Cache
615 .getProperty("SCREENGEOMETRY_WIDTH"))));
616 double sh = ((1f * screenSize.height) / (1f * Integer
617 .parseInt(jalview.bin.Cache
618 .getProperty("SCREENGEOMETRY_HEIGHT"))));
619 // rescale the bounds depending upon the current screen geometry.
620 ix = (int) (ix * sw);
621 iw = (int) (iw * sw);
622 iy = (int) (iy * sh);
623 ih = (int) (ih * sh);
624 while (ix >= screenSize.width)
626 jalview.bin.Cache.log
627 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
628 ix -= screenSize.width;
630 while (iy >= screenSize.height)
632 jalview.bin.Cache.log
633 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
634 iy -= screenSize.height;
636 jalview.bin.Cache.log.debug("Got last known dimensions for "
637 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
640 // return dimensions for new instance
641 return new Rectangle(ix, iy, iw, ih);
646 private void doVamsasClientCheck()
648 if (jalview.bin.Cache.vamsasJarsPresent())
650 setupVamsasDisconnectedGui();
651 VamsasMenu.setVisible(true);
652 final Desktop us = this;
653 VamsasMenu.addMenuListener(new MenuListener()
655 // this listener remembers when the menu was first selected, and
656 // doesn't rebuild the session list until it has been cleared and
658 boolean refresh = true;
661 public void menuCanceled(MenuEvent e)
667 public void menuDeselected(MenuEvent e)
673 public void menuSelected(MenuEvent e)
677 us.buildVamsasStMenu();
682 vamsasStart.setVisible(true);
686 void showPasteMenu(int x, int y)
688 JPopupMenu popup = new JPopupMenu();
689 JMenuItem item = new JMenuItem(
690 MessageManager.getString("label.paste_new_window"));
691 item.addActionListener(new ActionListener()
694 public void actionPerformed(ActionEvent evt)
701 popup.show(this, x, y);
708 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
709 Transferable contents = c.getContents(this);
711 if (contents != null)
713 String file = (String) contents
714 .getTransferData(DataFlavor.stringFlavor);
716 String format = new IdentifyFile().identify(file,
717 FormatAdapter.PASTE);
719 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
722 } catch (Exception ex)
725 .println("Unable to paste alignment from system clipboard:\n"
731 * Adds and opens the given frame to the desktop
742 public static synchronized void addInternalFrame(
743 final JInternalFrame frame, String title, int w, int h)
745 addInternalFrame(frame, title, true, w, h, true);
749 * Add an internal frame to the Jalview desktop
756 * When true, display frame immediately, otherwise, caller must call
757 * setVisible themselves.
763 public static synchronized void addInternalFrame(
764 final JInternalFrame frame, String title, boolean makeVisible,
767 addInternalFrame(frame, title, makeVisible, w, h, true);
771 * Add an internal frame to the Jalview desktop and make it visible
784 public static synchronized void addInternalFrame(
785 final JInternalFrame frame, String title, int w, int h,
788 addInternalFrame(frame, title, true, w, h, resizable);
792 * Add an internal frame to the Jalview desktop
799 * When true, display frame immediately, otherwise, caller must call
800 * setVisible themselves.
808 public static synchronized void addInternalFrame(
809 final JInternalFrame frame, String title, boolean makeVisible,
810 int w, int h, boolean resizable)
813 // TODO: allow callers to determine X and Y position of frame (eg. via
815 // TODO: consider fixing method to update entries in the window submenu with
816 // the current window title
818 frame.setTitle(title);
819 if (frame.getWidth() < 1 || frame.getHeight() < 1)
823 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
824 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
825 // IF JALVIEW IS RUNNING HEADLESS
826 // ///////////////////////////////////////////////
828 || (System.getProperty("java.awt.headless") != null && System
829 .getProperty("java.awt.headless").equals("true")))
836 frame.setVisible(makeVisible);
837 frame.setClosable(true);
838 frame.setResizable(resizable);
839 frame.setMaximizable(resizable);
840 frame.setIconifiable(resizable);
841 if (Platform.isAMac())
843 frame.setIconifiable(false);
844 frame.setFrameIcon(null);
845 // frame.setDesktopIcon(null);
846 frame.setDoubleBuffered(false);
848 if (frame.getX() < 1 && frame.getY() < 1)
850 frame.setLocation(xOffset * openFrameCount, yOffset
851 * ((openFrameCount - 1) % 10) + yOffset);
855 * add an entry for the new frame in the Window menu
856 * (and remove it when the frame is closed)
858 final JMenuItem menuItem = new JMenuItem(title);
859 frame.addInternalFrameListener(new InternalFrameAdapter()
862 public void internalFrameActivated(InternalFrameEvent evt)
864 JInternalFrame itf = desktop.getSelectedFrame();
872 public void internalFrameClosed(InternalFrameEvent evt)
874 PaintRefresher.RemoveComponent(frame);
877 * defensive check to prevent frames being
878 * added half off the window
880 if (openFrameCount > 0)
886 * ensure no reference to alignFrame retained by menu item listener
888 if (menuItem.getActionListeners().length > 0)
890 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
892 windowMenu.remove(menuItem);
893 JInternalFrame itf = desktop.getSelectedFrame();
897 if (itf instanceof AlignFrame)
899 Jalview.setCurrentAlignFrame((AlignFrame) itf);
906 menuItem.addActionListener(new ActionListener()
909 public void actionPerformed(ActionEvent e)
913 frame.setSelected(true);
914 frame.setIcon(false);
915 } catch (java.beans.PropertyVetoException ex)
922 windowMenu.add(menuItem);
928 frame.setSelected(true);
929 frame.requestFocus();
930 } catch (java.beans.PropertyVetoException ve)
932 } catch (java.lang.ClassCastException cex)
935 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
941 public void lostOwnership(Clipboard clipboard, Transferable contents)
945 Desktop.jalviewClipboard = null;
948 internalCopy = false;
952 public void dragEnter(DropTargetDragEvent evt)
957 public void dragExit(DropTargetEvent evt)
962 public void dragOver(DropTargetDragEvent evt)
967 public void dropActionChanged(DropTargetDragEvent evt)
978 public void drop(DropTargetDropEvent evt)
980 boolean success = true;
981 // JAL-1552 - acceptDrop required before getTransferable call for
982 // Java's Transferable for native dnd
983 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
984 Transferable t = evt.getTransferable();
985 java.util.List<String> files = new ArrayList<String>();
986 java.util.List<String> protocols = new ArrayList<String>();
990 Desktop.transferFromDropTarget(files, protocols, evt, t);
991 } catch (Exception e)
1001 for (int i = 0; i < files.size(); i++)
1003 String file = files.get(i).toString();
1004 String protocol = (protocols == null) ? FormatAdapter.FILE
1005 : (String) protocols.get(i);
1006 String format = null;
1008 if (file.endsWith(".jar"))
1015 format = new IdentifyFile().identify(file, protocol);
1018 new FileLoader().LoadFile(file, protocol, format);
1021 } catch (Exception ex)
1026 evt.dropComplete(success); // need this to ensure input focus is properly
1027 // transfered to any new windows created
1037 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1039 JalviewFileChooser chooser = new JalviewFileChooser(
1040 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1041 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
1042 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
1043 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
1045 chooser.setFileView(new JalviewFileView());
1046 chooser.setDialogTitle(MessageManager
1047 .getString("label.open_local_file"));
1048 chooser.setToolTipText(MessageManager.getString("action.open"));
1050 int value = chooser.showOpenDialog(this);
1052 if (value == JalviewFileChooser.APPROVE_OPTION)
1054 String choice = chooser.getSelectedFile().getPath();
1055 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1056 .getSelectedFile().getParent());
1058 String format = null;
1059 if (chooser.getSelectedFormat() != null
1060 && chooser.getSelectedFormat().equals("Jalview"))
1066 format = new IdentifyFile().identify(choice, FormatAdapter.FILE);
1069 if (viewport != null)
1071 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
1076 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
1088 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1090 // This construct allows us to have a wider textfield
1092 JLabel label = new JLabel(
1093 MessageManager.getString("label.input_file_url"));
1094 final JComboBox history = new JComboBox();
1096 JPanel panel = new JPanel(new GridLayout(2, 1));
1099 history.setPreferredSize(new Dimension(400, 20));
1100 history.setEditable(true);
1101 history.addItem("http://www.");
1103 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1107 if (historyItems != null)
1109 st = new StringTokenizer(historyItems, "\t");
1111 while (st.hasMoreTokens())
1113 history.addItem(st.nextElement());
1117 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
1118 MessageManager.getString("label.input_alignment_from_url"),
1119 JOptionPane.OK_CANCEL_OPTION);
1121 if (reply != JOptionPane.OK_OPTION)
1126 String url = history.getSelectedItem().toString();
1128 if (url.toLowerCase().endsWith(".jar"))
1130 if (viewport != null)
1132 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1137 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1142 String format = new IdentifyFile().identify(url, FormatAdapter.URL);
1144 if (format.equals("URL NOT FOUND"))
1146 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1147 MessageManager.formatMessage("label.couldnt_locate",
1148 new Object[] { url }), MessageManager
1149 .getString("label.url_not_found"),
1150 JOptionPane.WARNING_MESSAGE);
1155 if (viewport != null)
1157 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1161 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1167 * Opens the CutAndPaste window for the user to paste an alignment in to
1170 * - if not null, the pasted alignment is added to the current
1171 * alignment; if null, to a new alignment window
1174 public void inputTextboxMenuItem_actionPerformed(
1175 AlignmentViewPanel viewPanel)
1177 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1178 cap.setForInput(viewPanel);
1179 Desktop.addInternalFrame(cap,
1180 MessageManager.getString("label.cut_paste_alignmen_file"),
1190 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1192 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1193 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1195 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1196 getBounds().y, getWidth(), getHeight()));
1198 if (jconsole != null)
1200 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1201 jconsole.stopConsole();
1205 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1208 if (dialogExecutor != null)
1210 dialogExecutor.shutdownNow();
1212 closeAll_actionPerformed(null);
1214 if (groovyConsole != null)
1216 // suppress a possible repeat prompt to save script
1217 groovyConsole.setDirty(false);
1218 groovyConsole.exit();
1223 private void storeLastKnownDimensions(String string, Rectangle jc)
1225 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1226 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1227 + " height:" + jc.height);
1229 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1230 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1231 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1232 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1242 public void aboutMenuItem_actionPerformed(ActionEvent e)
1244 // StringBuffer message = getAboutMessage(false);
1245 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1247 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1248 new Thread(new Runnable()
1253 new SplashScreen(true);
1258 public StringBuffer getAboutMessage(boolean shortv)
1260 StringBuffer message = new StringBuffer();
1261 message.append("<html>");
1264 message.append("<h1><strong>Version: "
1265 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1266 message.append("<strong>Last Updated: <em>"
1267 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1268 + "</em></strong>");
1274 message.append("<strong>Version "
1275 + jalview.bin.Cache.getProperty("VERSION")
1276 + "; last updated: "
1277 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1280 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1283 message.append("<br>...Checking latest version...</br>");
1285 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1286 .equals(jalview.bin.Cache.getProperty("VERSION")))
1288 boolean red = false;
1289 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1290 .indexOf("automated build") == -1)
1293 // Displayed when code version and jnlp version do not match and code
1294 // version is not a development build
1295 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1298 message.append("<br>!! Version "
1299 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1301 + " is available for download from "
1302 + jalview.bin.Cache.getDefault("www.jalview.org",
1303 "http://www.jalview.org") + " !!");
1306 message.append("</div>");
1309 message.append("<br>Authors: "
1311 .getDefault("AUTHORFNAMES",
1312 "The Jalview Authors (See AUTHORS file for current list)")
1313 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1314 + "<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"
1315 + "<br><br>If you use Jalview, please cite:"
1316 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1317 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1318 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1330 public void documentationMenuItem_actionPerformed(ActionEvent e)
1334 Help.showHelpWindow();
1335 } catch (Exception ex)
1341 public void closeAll_actionPerformed(ActionEvent e)
1343 // TODO show a progress bar while closing?
1344 JInternalFrame[] frames = desktop.getAllFrames();
1345 for (int i = 0; i < frames.length; i++)
1349 frames[i].setClosed(true);
1350 } catch (java.beans.PropertyVetoException ex)
1354 Jalview.setCurrentAlignFrame(null);
1355 System.out.println("ALL CLOSED");
1356 if (v_client != null)
1358 // TODO clear binding to vamsas document objects on close_all
1362 * reset state of singleton objects as appropriate (clear down session state
1363 * when all windows are closed)
1365 StructureSelectionManager ssm = StructureSelectionManager
1366 .getStructureSelectionManager(this);
1375 public void raiseRelated_actionPerformed(ActionEvent e)
1377 reorderAssociatedWindows(false, false);
1381 public void minimizeAssociated_actionPerformed(ActionEvent e)
1383 reorderAssociatedWindows(true, false);
1386 void closeAssociatedWindows()
1388 reorderAssociatedWindows(false, true);
1394 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1398 protected void garbageCollect_actionPerformed(ActionEvent e)
1400 // We simply collect the garbage
1401 jalview.bin.Cache.log.debug("Collecting garbage...");
1403 jalview.bin.Cache.log.debug("Finished garbage collection.");
1410 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1414 protected void showMemusage_actionPerformed(ActionEvent e)
1416 desktop.showMemoryUsage(showMemusage.isSelected());
1423 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1427 protected void showConsole_actionPerformed(ActionEvent e)
1429 showConsole(showConsole.isSelected());
1432 Console jconsole = null;
1435 * control whether the java console is visible or not
1439 void showConsole(boolean selected)
1441 showConsole.setSelected(selected);
1442 // TODO: decide if we should update properties file
1443 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1445 jconsole.setVisible(selected);
1448 void reorderAssociatedWindows(boolean minimize, boolean close)
1450 JInternalFrame[] frames = desktop.getAllFrames();
1451 if (frames == null || frames.length < 1)
1456 AlignmentViewport source = null, target = null;
1457 if (frames[0] instanceof AlignFrame)
1459 source = ((AlignFrame) frames[0]).getCurrentView();
1461 else if (frames[0] instanceof TreePanel)
1463 source = ((TreePanel) frames[0]).getViewPort();
1465 else if (frames[0] instanceof PCAPanel)
1467 source = ((PCAPanel) frames[0]).av;
1469 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1471 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1476 for (int i = 0; i < frames.length; i++)
1479 if (frames[i] == null)
1483 if (frames[i] instanceof AlignFrame)
1485 target = ((AlignFrame) frames[i]).getCurrentView();
1487 else if (frames[i] instanceof TreePanel)
1489 target = ((TreePanel) frames[i]).getViewPort();
1491 else if (frames[i] instanceof PCAPanel)
1493 target = ((PCAPanel) frames[i]).av;
1495 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1497 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1500 if (source == target)
1506 frames[i].setClosed(true);
1510 frames[i].setIcon(minimize);
1513 frames[i].toFront();
1517 } catch (java.beans.PropertyVetoException ex)
1532 protected void preferences_actionPerformed(ActionEvent e)
1544 public void saveState_actionPerformed(ActionEvent e)
1546 JalviewFileChooser chooser = new JalviewFileChooser(
1547 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1548 new String[] { "jvp" }, new String[] { "Jalview Project" },
1551 chooser.setFileView(new JalviewFileView());
1552 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1554 int value = chooser.showSaveDialog(this);
1556 if (value == JalviewFileChooser.APPROVE_OPTION)
1558 final Desktop me = this;
1559 final java.io.File choice = chooser.getSelectedFile();
1560 setProjectFile(choice);
1562 new Thread(new Runnable()
1567 // TODO: refactor to Jalview desktop session controller action.
1568 setProgressBar(MessageManager.formatMessage(
1569 "label.saving_jalview_project",
1570 new Object[] { choice.getName() }), choice.hashCode());
1571 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1572 choice.getParent());
1573 // TODO catch and handle errors for savestate
1574 // TODO prevent user from messing with the Desktop whilst we're saving
1577 new Jalview2XML().saveState(choice);
1578 } catch (OutOfMemoryError oom)
1580 new OOMWarning("Whilst saving current state to "
1581 + choice.getName(), oom);
1582 } catch (Exception ex)
1585 "Problems whilst trying to save to " + choice.getName(),
1587 JOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1588 "label.error_whilst_saving_current_state_to",
1589 new Object[] { choice.getName() }), MessageManager
1590 .getString("label.couldnt_save_project"),
1591 JOptionPane.WARNING_MESSAGE);
1593 setProgressBar(null, choice.hashCode());
1599 private void setProjectFile(File choice)
1601 this.projectFile = choice;
1604 public File getProjectFile()
1606 return this.projectFile;
1616 public void loadState_actionPerformed(ActionEvent e)
1618 JalviewFileChooser chooser = new JalviewFileChooser(
1619 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] {
1620 "jvp", "jar" }, new String[] { "Jalview Project",
1621 "Jalview Project (old)" }, "Jalview Project");
1622 chooser.setFileView(new JalviewFileView());
1623 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1625 int value = chooser.showOpenDialog(this);
1627 if (value == JalviewFileChooser.APPROVE_OPTION)
1629 final File selectedFile = chooser.getSelectedFile();
1630 setProjectFile(selectedFile);
1631 final String choice = selectedFile.getAbsolutePath();
1632 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1633 selectedFile.getParent());
1634 new Thread(new Runnable()
1640 MessageManager.formatMessage(
1641 "label.loading_jalview_project",
1642 new Object[] { choice }), choice.hashCode());
1645 new Jalview2XML().loadJalviewAlign(choice);
1646 } catch (OutOfMemoryError oom)
1648 new OOMWarning("Whilst loading project from " + choice, oom);
1649 } catch (Exception ex)
1651 Cache.log.error("Problems whilst loading project from "
1653 JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1655 "label.error_whilst_loading_project_from",
1656 new Object[] { choice }), MessageManager
1657 .getString("label.couldnt_load_project"),
1658 JOptionPane.WARNING_MESSAGE);
1660 setProgressBar(null, choice.hashCode());
1667 public void inputSequence_actionPerformed(ActionEvent e)
1669 new SequenceFetcher(this);
1672 JPanel progressPanel;
1674 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1676 public void startLoading(final String fileName)
1678 if (fileLoadingCount == 0)
1680 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1681 "label.loading_file", new Object[] { fileName })));
1686 private JPanel addProgressPanel(String string)
1688 if (progressPanel == null)
1690 progressPanel = new JPanel(new GridLayout(1, 1));
1691 totalProgressCount = 0;
1692 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1694 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1695 JProgressBar progressBar = new JProgressBar();
1696 progressBar.setIndeterminate(true);
1698 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1700 thisprogress.add(progressBar, BorderLayout.CENTER);
1701 progressPanel.add(thisprogress);
1702 ((GridLayout) progressPanel.getLayout())
1703 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1704 ++totalProgressCount;
1705 instance.validate();
1706 return thisprogress;
1709 int totalProgressCount = 0;
1711 private void removeProgressPanel(JPanel progbar)
1713 if (progressPanel != null)
1715 synchronized (progressPanel)
1717 progressPanel.remove(progbar);
1718 GridLayout gl = (GridLayout) progressPanel.getLayout();
1719 gl.setRows(gl.getRows() - 1);
1720 if (--totalProgressCount < 1)
1722 this.getContentPane().remove(progressPanel);
1723 progressPanel = null;
1730 public void stopLoading()
1733 if (fileLoadingCount < 1)
1735 while (fileLoadingPanels.size() > 0)
1737 removeProgressPanel(fileLoadingPanels.remove(0));
1739 fileLoadingPanels.clear();
1740 fileLoadingCount = 0;
1745 public static int getViewCount(String alignmentId)
1747 AlignmentViewport[] aps = getViewports(alignmentId);
1748 return (aps == null) ? 0 : aps.length;
1753 * @param alignmentId
1754 * - if null, all sets are returned
1755 * @return all AlignmentPanels concerning the alignmentId sequence set
1757 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1759 if (Desktop.desktop == null)
1761 // no frames created and in headless mode
1762 // TODO: verify that frames are recoverable when in headless mode
1765 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1766 AlignFrame[] frames = getAlignFrames();
1771 for (AlignFrame af : frames)
1773 for (AlignmentPanel ap : af.alignPanels)
1775 if (alignmentId == null
1776 || alignmentId.equals(ap.av.getSequenceSetId()))
1782 if (aps.size() == 0)
1786 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1791 * get all the viewports on an alignment.
1793 * @param sequenceSetId
1794 * unique alignment id (may be null - all viewports returned in that
1796 * @return all viewports on the alignment bound to sequenceSetId
1798 public static AlignmentViewport[] getViewports(String sequenceSetId)
1800 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1801 if (desktop != null)
1803 AlignFrame[] frames = Desktop.getAlignFrames();
1805 for (AlignFrame afr : frames)
1807 if (sequenceSetId == null
1808 || afr.getViewport().getSequenceSetId()
1809 .equals(sequenceSetId))
1811 if (afr.alignPanels != null)
1813 for (AlignmentPanel ap : afr.alignPanels)
1815 if (sequenceSetId == null
1816 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1824 viewp.add(afr.getViewport());
1828 if (viewp.size() > 0)
1830 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1837 * Explode the views in the given frame into separate AlignFrame
1841 public static void explodeViews(AlignFrame af)
1843 int size = af.alignPanels.size();
1849 for (int i = 0; i < size; i++)
1851 AlignmentPanel ap = af.alignPanels.get(i);
1852 AlignFrame newaf = new AlignFrame(ap);
1855 * Restore the view's last exploded frame geometry if known. Multiple
1856 * views from one exploded frame share and restore the same (frame)
1857 * position and size.
1859 Rectangle geometry = ap.av.getExplodedGeometry();
1860 if (geometry != null)
1862 newaf.setBounds(geometry);
1865 ap.av.setGatherViewsHere(false);
1867 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1868 AlignFrame.DEFAULT_HEIGHT);
1871 af.alignPanels.clear();
1872 af.closeMenuItem_actionPerformed(true);
1877 * Gather expanded views (separate AlignFrame's) with the same sequence set
1878 * identifier back in to this frame as additional views, and close the
1879 * expanded views. Note the expanded frames may themselves have multiple
1880 * views. We take the lot.
1884 public void gatherViews(AlignFrame source)
1886 source.viewport.setGatherViewsHere(true);
1887 source.viewport.setExplodedGeometry(source.getBounds());
1888 JInternalFrame[] frames = desktop.getAllFrames();
1889 String viewId = source.viewport.getSequenceSetId();
1891 for (int t = 0; t < frames.length; t++)
1893 if (frames[t] instanceof AlignFrame && frames[t] != source)
1895 AlignFrame af = (AlignFrame) frames[t];
1896 boolean gatherThis = false;
1897 for (int a = 0; a < af.alignPanels.size(); a++)
1899 AlignmentPanel ap = af.alignPanels.get(a);
1900 if (viewId.equals(ap.av.getSequenceSetId()))
1903 ap.av.setGatherViewsHere(false);
1904 ap.av.setExplodedGeometry(af.getBounds());
1905 source.addAlignmentPanel(ap, false);
1911 af.alignPanels.clear();
1912 af.closeMenuItem_actionPerformed(true);
1919 jalview.gui.VamsasApplication v_client = null;
1922 public void vamsasImport_actionPerformed(ActionEvent e)
1924 if (v_client == null)
1926 // Load and try to start a session.
1927 JalviewFileChooser chooser = new JalviewFileChooser(
1928 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1930 chooser.setFileView(new JalviewFileView());
1931 chooser.setDialogTitle(MessageManager
1932 .getString("label.open_saved_vamsas_session"));
1933 chooser.setToolTipText(MessageManager
1934 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1936 int value = chooser.showOpenDialog(this);
1938 if (value == JalviewFileChooser.APPROVE_OPTION)
1940 String fle = chooser.getSelectedFile().toString();
1941 if (!vamsasImport(chooser.getSelectedFile()))
1944 .showInternalMessageDialog(
1946 MessageManager.formatMessage(
1947 "label.couldnt_import_as_vamsas_session",
1948 new Object[] { fle }),
1950 .getString("label.vamsas_document_import_failed"),
1951 JOptionPane.ERROR_MESSAGE);
1957 jalview.bin.Cache.log
1958 .error("Implementation error - load session from a running session is not supported.");
1963 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1966 * @return true if import was a success and a session was started.
1968 public boolean vamsasImport(URL url)
1970 // TODO: create progress bar
1971 if (v_client != null)
1974 jalview.bin.Cache.log
1975 .error("Implementation error - load session from a running session is not supported.");
1981 // copy the URL content to a temporary local file
1982 // TODO: be a bit cleverer here with nio (?!)
1983 File file = File.createTempFile("vdocfromurl", ".vdj");
1984 FileOutputStream fos = new FileOutputStream(file);
1985 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1986 byte[] buffer = new byte[2048];
1988 while ((ln = bis.read(buffer)) > -1)
1990 fos.write(buffer, 0, ln);
1994 v_client = new jalview.gui.VamsasApplication(this, file,
1995 url.toExternalForm());
1996 } catch (Exception ex)
1998 jalview.bin.Cache.log.error(
1999 "Failed to create new vamsas session from contents of URL "
2003 setupVamsasConnectedGui();
2004 v_client.initial_update(); // TODO: thread ?
2005 return v_client.inSession();
2009 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2012 * @return true if import was a success and a session was started.
2014 public boolean vamsasImport(File file)
2016 if (v_client != null)
2019 jalview.bin.Cache.log
2020 .error("Implementation error - load session from a running session is not supported.");
2024 setProgressBar(MessageManager.formatMessage(
2025 "status.importing_vamsas_session_from",
2026 new Object[] { file.getName() }), file.hashCode());
2029 v_client = new jalview.gui.VamsasApplication(this, file, null);
2030 } catch (Exception ex)
2032 setProgressBar(MessageManager.formatMessage(
2033 "status.importing_vamsas_session_from",
2034 new Object[] { file.getName() }), file.hashCode());
2035 jalview.bin.Cache.log.error(
2036 "New vamsas session from existing session file failed:", ex);
2039 setupVamsasConnectedGui();
2040 v_client.initial_update(); // TODO: thread ?
2041 setProgressBar(MessageManager.formatMessage(
2042 "status.importing_vamsas_session_from",
2043 new Object[] { file.getName() }), file.hashCode());
2044 return v_client.inSession();
2047 public boolean joinVamsasSession(String mysesid)
2049 if (v_client != null)
2053 .getString("error.try_join_vamsas_session_another"));
2055 if (mysesid == null)
2058 MessageManager.getString("error.invalid_vamsas_session_id"));
2060 v_client = new VamsasApplication(this, mysesid);
2061 setupVamsasConnectedGui();
2062 v_client.initial_update();
2063 return (v_client.inSession());
2067 public void vamsasStart_actionPerformed(ActionEvent e)
2069 if (v_client == null)
2072 // we just start a default session for moment.
2074 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2075 * getProperty("LAST_DIRECTORY"));
2077 * chooser.setFileView(new JalviewFileView());
2078 * chooser.setDialogTitle("Load Vamsas file");
2079 * chooser.setToolTipText("Import");
2081 * int value = chooser.showOpenDialog(this);
2083 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2084 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2086 v_client = new VamsasApplication(this);
2087 setupVamsasConnectedGui();
2088 v_client.initial_update(); // TODO: thread ?
2092 // store current data in session.
2093 v_client.push_update(); // TODO: thread
2097 protected void setupVamsasConnectedGui()
2099 vamsasStart.setText(MessageManager.getString("label.session_update"));
2100 vamsasSave.setVisible(true);
2101 vamsasStop.setVisible(true);
2102 vamsasImport.setVisible(false); // Document import to existing session is
2103 // not possible for vamsas-client-1.0.
2106 protected void setupVamsasDisconnectedGui()
2108 vamsasSave.setVisible(false);
2109 vamsasStop.setVisible(false);
2110 vamsasImport.setVisible(true);
2111 vamsasStart.setText(MessageManager
2112 .getString("label.new_vamsas_session"));
2116 public void vamsasStop_actionPerformed(ActionEvent e)
2118 if (v_client != null)
2120 v_client.end_session();
2122 setupVamsasDisconnectedGui();
2126 protected void buildVamsasStMenu()
2128 if (v_client == null)
2130 String[] sess = null;
2133 sess = VamsasApplication.getSessionList();
2134 } catch (Exception e)
2136 jalview.bin.Cache.log.warn(
2137 "Problem getting current sessions list.", e);
2142 jalview.bin.Cache.log.debug("Got current sessions list: "
2143 + sess.length + " entries.");
2144 VamsasStMenu.removeAll();
2145 for (int i = 0; i < sess.length; i++)
2147 JMenuItem sessit = new JMenuItem();
2148 sessit.setText(sess[i]);
2149 sessit.setToolTipText(MessageManager.formatMessage(
2150 "label.connect_to_session", new Object[] { sess[i] }));
2151 final Desktop dsktp = this;
2152 final String mysesid = sess[i];
2153 sessit.addActionListener(new ActionListener()
2157 public void actionPerformed(ActionEvent e)
2159 if (dsktp.v_client == null)
2161 Thread rthr = new Thread(new Runnable()
2167 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2168 dsktp.setupVamsasConnectedGui();
2169 dsktp.v_client.initial_update();
2177 VamsasStMenu.add(sessit);
2179 // don't show an empty menu.
2180 VamsasStMenu.setVisible(sess.length > 0);
2185 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2186 VamsasStMenu.removeAll();
2187 VamsasStMenu.setVisible(false);
2192 // Not interested in the content. Just hide ourselves.
2193 VamsasStMenu.setVisible(false);
2198 public void vamsasSave_actionPerformed(ActionEvent e)
2200 if (v_client != null)
2202 JalviewFileChooser chooser = new JalviewFileChooser(
2203 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
2204 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2205 new String[] { "Vamsas Document" }, "Vamsas Document");
2207 chooser.setFileView(new JalviewFileView());
2208 chooser.setDialogTitle(MessageManager
2209 .getString("label.save_vamsas_document_archive"));
2211 int value = chooser.showSaveDialog(this);
2213 if (value == JalviewFileChooser.APPROVE_OPTION)
2215 java.io.File choice = chooser.getSelectedFile();
2216 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2217 "label.saving_vamsas_doc",
2218 new Object[] { choice.getName() }));
2219 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2220 String warnmsg = null;
2221 String warnttl = null;
2224 v_client.vclient.storeDocument(choice);
2227 warnttl = "Serious Problem saving Vamsas Document";
2228 warnmsg = ex.toString();
2229 jalview.bin.Cache.log.error("Error Whilst saving document to "
2232 } catch (Exception ex)
2234 warnttl = "Problem saving Vamsas Document.";
2235 warnmsg = ex.toString();
2236 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2240 removeProgressPanel(progpanel);
2241 if (warnmsg != null)
2243 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2245 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2251 JPanel vamUpdate = null;
2254 * hide vamsas user gui bits when a vamsas document event is being handled.
2257 * true to hide gui, false to reveal gui
2259 public void setVamsasUpdate(boolean b)
2261 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2262 + (b ? "in progress" : "finished"));
2264 if (vamUpdate != null)
2266 this.removeProgressPanel(vamUpdate);
2270 vamUpdate = this.addProgressPanel(MessageManager
2271 .getString("label.updating_vamsas_session"));
2273 vamsasStart.setVisible(!b);
2274 vamsasStop.setVisible(!b);
2275 vamsasSave.setVisible(!b);
2278 public JInternalFrame[] getAllFrames()
2280 return desktop.getAllFrames();
2284 * Checks the given url to see if it gives a response indicating that the user
2285 * should be informed of a new questionnaire.
2289 public void checkForQuestionnaire(String url)
2291 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2292 // javax.swing.SwingUtilities.invokeLater(jvq);
2293 new Thread(jvq).start();
2296 public void checkURLLinks()
2298 // Thread off the URL link checker
2299 addDialogThread(new Runnable()
2304 if (Cache.getDefault("CHECKURLLINKS", true))
2306 // check what the actual links are - if it's just the default don't
2307 // bother with the warning
2308 Vector<String> links = Preferences.sequenceUrlLinks
2311 // only need to check links if there is one with a
2312 // SEQUENCE_ID which is not the default EMBL_EBI link
2313 ListIterator<String> li = links.listIterator();
2314 boolean check = false;
2315 List<JLabel> urls = new ArrayList<JLabel>();
2316 while (li.hasNext())
2318 String link = li.next();
2319 if (link.contains(SEQUENCE_ID)
2320 && !link.equals(UrlConstants.DEFAULT_STRING))
2323 int barPos = link.indexOf("|");
2324 String urlMsg = barPos == -1 ? link : link.substring(0,
2325 barPos) + ": " + link.substring(barPos + 1);
2326 urls.add(new JLabel(urlMsg));
2334 // ask user to check in case URL links use old style tokens
2335 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2336 JPanel msgPanel = new JPanel();
2337 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2338 msgPanel.add(Box.createVerticalGlue());
2339 JLabel msg = new JLabel(
2341 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2342 JLabel msg2 = new JLabel(
2344 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2346 for (JLabel url : urls)
2352 final JCheckBox jcb = new JCheckBox(
2353 MessageManager.getString("label.do_not_display_again"));
2354 jcb.addActionListener(new ActionListener()
2357 public void actionPerformed(ActionEvent e)
2359 // update Cache settings for "don't show this again"
2360 boolean showWarningAgain = !jcb.isSelected();
2361 Cache.setProperty("CHECKURLLINKS",
2362 Boolean.valueOf(showWarningAgain).toString());
2367 JOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2369 .getString("label.SEQUENCE_ID_no_longer_used"),
2370 JOptionPane.WARNING_MESSAGE);
2377 * Proxy class for JDesktopPane which optionally displays the current memory
2378 * usage and highlights the desktop area with a red bar if free memory runs
2383 public class MyDesktopPane extends JDesktopPane implements Runnable
2386 private static final float ONE_MB = 1048576f;
2388 boolean showMemoryUsage = false;
2392 java.text.NumberFormat df;
2394 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2397 public MyDesktopPane(boolean showMemoryUsage)
2399 showMemoryUsage(showMemoryUsage);
2402 public void showMemoryUsage(boolean showMemory)
2404 this.showMemoryUsage = showMemory;
2407 Thread worker = new Thread(this);
2412 public boolean isShowMemoryUsage()
2414 return showMemoryUsage;
2420 df = java.text.NumberFormat.getNumberInstance();
2421 df.setMaximumFractionDigits(2);
2422 runtime = Runtime.getRuntime();
2424 while (showMemoryUsage)
2428 maxMemory = runtime.maxMemory() / ONE_MB;
2429 allocatedMemory = runtime.totalMemory() / ONE_MB;
2430 freeMemory = runtime.freeMemory() / ONE_MB;
2431 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2433 percentUsage = (totalFreeMemory / maxMemory) * 100;
2435 // if (percentUsage < 20)
2437 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2439 // instance.set.setBorder(border1);
2442 // sleep after showing usage
2444 } catch (Exception ex)
2446 ex.printStackTrace();
2452 public void paintComponent(Graphics g)
2454 if (showMemoryUsage && g != null && df != null)
2456 if (percentUsage < 20)
2458 g.setColor(Color.red);
2460 FontMetrics fm = g.getFontMetrics();
2463 g.drawString(MessageManager.formatMessage(
2464 "label.memory_stats",
2465 new Object[] { df.format(totalFreeMemory),
2466 df.format(maxMemory), df.format(percentUsage) }), 10,
2467 getHeight() - fm.getHeight());
2474 * fixes stacking order after a modal dialog to ensure windows that should be
2475 * on top actually are
2477 public void relayerWindows()
2482 protected JMenuItem groovyShell;
2485 * Accessor method to quickly get all the AlignmentFrames loaded.
2487 * @return an array of AlignFrame, or null if none found
2489 public static AlignFrame[] getAlignFrames()
2491 if (Jalview.isHeadlessMode())
2493 // Desktop.desktop is null in headless mode
2494 return new AlignFrame[] { Jalview.currentAlignFrame };
2497 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2503 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2505 for (int i = frames.length - 1; i > -1; i--)
2507 if (frames[i] instanceof AlignFrame)
2509 avp.add((AlignFrame) frames[i]);
2511 else if (frames[i] instanceof SplitFrame)
2514 * Also check for a split frame containing an AlignFrame
2516 GSplitFrame sf = (GSplitFrame) frames[i];
2517 if (sf.getTopFrame() instanceof AlignFrame)
2519 avp.add((AlignFrame) sf.getTopFrame());
2521 if (sf.getBottomFrame() instanceof AlignFrame)
2523 avp.add((AlignFrame) sf.getBottomFrame());
2527 if (avp.size() == 0)
2531 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2536 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2540 public GStructureViewer[] getJmols()
2542 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2548 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2550 for (int i = frames.length - 1; i > -1; i--)
2552 if (frames[i] instanceof AppJmol)
2554 GStructureViewer af = (GStructureViewer) frames[i];
2558 if (avp.size() == 0)
2562 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2567 * Add Groovy Support to Jalview
2569 public void groovyShell_actionPerformed()
2573 openGroovyConsole();
2574 } catch (Exception ex)
2576 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2577 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2579 MessageManager.getString("label.couldnt_create_groovy_shell"),
2580 MessageManager.getString("label.groovy_support_failed"),
2581 JOptionPane.ERROR_MESSAGE);
2586 * Open the Groovy console
2588 void openGroovyConsole()
2590 if (groovyConsole == null)
2592 groovyConsole = new groovy.ui.Console();
2593 groovyConsole.setVariable("Jalview", this);
2594 groovyConsole.run();
2597 * We allow only one console at a time, so that AlignFrame menu option
2598 * 'Calculate | Run Groovy script' is unambiguous.
2599 * Disable 'Groovy Console', and enable 'Run script', when the console is
2600 * opened, and the reverse when it is closed
2602 Window window = (Window) groovyConsole.getFrame();
2603 window.addWindowListener(new WindowAdapter()
2606 public void windowClosed(WindowEvent e)
2609 * rebind CMD-Q from Groovy Console to Jalview Quit
2612 enableExecuteGroovy(false);
2618 * show Groovy console window (after close and reopen)
2620 ((Window) groovyConsole.getFrame()).setVisible(true);
2623 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2624 * and disable opening a second console
2626 enableExecuteGroovy(true);
2630 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2631 * binding when opened
2633 protected void addQuitHandler()
2635 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2636 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2637 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2638 getRootPane().getActionMap().put("Quit", new AbstractAction()
2641 public void actionPerformed(ActionEvent e)
2649 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2652 * true if Groovy console is open
2654 public void enableExecuteGroovy(boolean enabled)
2657 * disable opening a second Groovy console
2658 * (or re-enable when the console is closed)
2660 groovyShell.setEnabled(!enabled);
2662 AlignFrame[] alignFrames = getAlignFrames();
2663 if (alignFrames != null)
2665 for (AlignFrame af : alignFrames)
2667 af.setGroovyEnabled(enabled);
2673 * Progress bars managed by the IProgressIndicator method.
2675 private Hashtable<Long, JPanel> progressBars;
2677 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2682 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2685 public void setProgressBar(String message, long id)
2687 if (progressBars == null)
2689 progressBars = new Hashtable<Long, JPanel>();
2690 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2693 if (progressBars.get(new Long(id)) != null)
2695 JPanel panel = progressBars.remove(new Long(id));
2696 if (progressBarHandlers.contains(new Long(id)))
2698 progressBarHandlers.remove(new Long(id));
2700 removeProgressPanel(panel);
2704 progressBars.put(new Long(id), addProgressPanel(message));
2711 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2712 * jalview.gui.IProgressIndicatorHandler)
2715 public void registerHandler(final long id,
2716 final IProgressIndicatorHandler handler)
2718 if (progressBarHandlers == null
2719 || !progressBars.containsKey(new Long(id)))
2723 .getString("error.call_setprogressbar_before_registering_handler"));
2725 progressBarHandlers.put(new Long(id), handler);
2726 final JPanel progressPanel = progressBars.get(new Long(id));
2727 if (handler.canCancel())
2729 JButton cancel = new JButton(
2730 MessageManager.getString("action.cancel"));
2731 final IProgressIndicator us = this;
2732 cancel.addActionListener(new ActionListener()
2736 public void actionPerformed(ActionEvent e)
2738 handler.cancelActivity(id);
2739 us.setProgressBar(MessageManager.formatMessage(
2740 "label.cancelled_params",
2741 new Object[] { ((JLabel) progressPanel.getComponent(0))
2745 progressPanel.add(cancel, BorderLayout.EAST);
2751 * @return true if any progress bars are still active
2754 public boolean operationInProgress()
2756 if (progressBars != null && progressBars.size() > 0)
2764 * This will return the first AlignFrame holding the given viewport instance.
2765 * It will break if there are more than one AlignFrames viewing a particular
2769 * @return alignFrame for viewport
2771 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2773 if (desktop != null)
2775 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2776 for (int panel = 0; aps != null && panel < aps.length; panel++)
2778 if (aps[panel] != null && aps[panel].av == viewport)
2780 return aps[panel].alignFrame;
2787 public VamsasApplication getVamsasApplication()
2794 * flag set if jalview GUI is being operated programmatically
2796 private boolean inBatchMode = false;
2799 * check if jalview GUI is being operated programmatically
2801 * @return inBatchMode
2803 public boolean isInBatchMode()
2809 * set flag if jalview GUI is being operated programmatically
2811 * @param inBatchMode
2813 public void setInBatchMode(boolean inBatchMode)
2815 this.inBatchMode = inBatchMode;
2818 public void startServiceDiscovery()
2820 startServiceDiscovery(false);
2823 public void startServiceDiscovery(boolean blocking)
2825 boolean alive = true;
2826 Thread t0 = null, t1 = null, t2 = null;
2827 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2830 // todo: changesupport handlers need to be transferred
2831 if (discoverer == null)
2833 discoverer = new jalview.ws.jws1.Discoverer();
2834 // register PCS handler for desktop.
2835 discoverer.addPropertyChangeListener(changeSupport);
2837 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2838 // until we phase out completely
2839 (t0 = new Thread(discoverer)).start();
2842 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2844 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2846 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2848 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2854 // TODO: do rest service discovery
2863 } catch (Exception e)
2866 alive = (t1 != null && t1.isAlive())
2867 || (t2 != null && t2.isAlive())
2868 || (t3 != null && t3.isAlive())
2869 || (t0 != null && t0.isAlive());
2875 * called to check if the service discovery process completed successfully.
2879 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2881 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2883 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2884 .getErrorMessages();
2887 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2889 if (serviceChangedDialog == null)
2891 // only run if we aren't already displaying one of these.
2892 addDialogThread(serviceChangedDialog = new Runnable()
2899 * JalviewDialog jd =new JalviewDialog() {
2901 * @Override protected void cancelPressed() { // TODO
2902 * Auto-generated method stub
2904 * }@Override protected void okPressed() { // TODO
2905 * Auto-generated method stub
2907 * }@Override protected void raiseClosed() { // TODO
2908 * Auto-generated method stub
2910 * } }; jd.initDialogFrame(new
2911 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2912 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2913 * + " or mis-configured HTTP proxy settings.<br/>" +
2914 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2916 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2917 * ), true, true, "Web Service Configuration Problem", 450,
2920 * jd.waitForInput();
2926 "<html><table width=\"450\"><tr><td>"
2928 + "</td></tr></table>"
2929 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2930 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2931 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2932 + " Tools->Preferences dialog box to change them.</p></html>"),
2933 "Web Service Configuration Problem",
2934 JOptionPane.DEFAULT_OPTION,
2935 JOptionPane.ERROR_MESSAGE);
2936 serviceChangedDialog = null;
2945 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2952 private Runnable serviceChangedDialog = null;
2955 * start a thread to open a URL in the configured browser. Pops up a warning
2956 * dialog to the user if there is an exception when calling out to the browser
2961 public static void showUrl(final String url)
2963 showUrl(url, Desktop.instance);
2967 * Like showUrl but allows progress handler to be specified
2971 * (null) or object implementing IProgressIndicator
2973 public static void showUrl(final String url,
2974 final IProgressIndicator progress)
2976 new Thread(new Runnable()
2983 if (progress != null)
2985 progress.setProgressBar(MessageManager.formatMessage(
2986 "status.opening_params", new Object[] { url }), this
2989 jalview.util.BrowserLauncher.openURL(url);
2990 } catch (Exception ex)
2992 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2994 .getString("label.web_browser_not_found_unix"),
2995 MessageManager.getString("label.web_browser_not_found"),
2996 JOptionPane.WARNING_MESSAGE);
2998 ex.printStackTrace();
3000 if (progress != null)
3002 progress.setProgressBar(null, this.hashCode());
3008 public static WsParamSetManager wsparamManager = null;
3010 public static ParamManager getUserParameterStore()
3012 if (wsparamManager == null)
3014 wsparamManager = new WsParamSetManager();
3016 return wsparamManager;
3020 * static hyperlink handler proxy method for use by Jalview's internal windows
3024 public static void hyperlinkUpdate(HyperlinkEvent e)
3026 if (e.getEventType() == EventType.ACTIVATED)
3031 url = e.getURL().toString();
3032 Desktop.showUrl(url);
3033 } catch (Exception x)
3037 if (Cache.log != null)
3039 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3043 System.err.println("Couldn't handle string " + url
3047 // ignore any exceptions due to dud links.
3054 * single thread that handles display of dialogs to user.
3056 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3059 * flag indicating if dialogExecutor should try to acquire a permit
3061 private volatile boolean dialogPause = true;
3066 private java.util.concurrent.Semaphore block = new Semaphore(0);
3068 private static groovy.ui.Console groovyConsole;
3071 * add another dialog thread to the queue
3075 public void addDialogThread(final Runnable prompter)
3077 dialogExecutor.submit(new Runnable()
3087 } catch (InterruptedException x)
3092 if (instance == null)
3098 SwingUtilities.invokeAndWait(prompter);
3099 } catch (Exception q)
3101 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3107 public void startDialogQueue()
3109 // set the flag so we don't pause waiting for another permit and semaphore
3110 // the current task to begin
3111 dialogPause = false;
3116 protected void snapShotWindow_actionPerformed(ActionEvent e)
3120 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3121 "View of Desktop", getWidth(), getHeight(), of = new File(
3122 "Jalview_snapshot" + System.currentTimeMillis()
3123 + ".eps"), "View of desktop", null, 0, false);
3126 paintAll(im.getGraphics());
3128 } catch (Exception q)
3130 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3134 Cache.log.info("Successfully written snapshot to file "
3135 + of.getAbsolutePath());
3139 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3140 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3141 * and location last time the view was expanded (if any). However it does not
3142 * remember the split pane divider location - this is set to match the
3143 * 'exploding' frame.
3147 public void explodeViews(SplitFrame sf)
3149 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3150 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3151 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3153 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3155 int viewCount = topPanels.size();
3162 * Processing in reverse order works, forwards order leaves the first panels
3163 * not visible. I don't know why!
3165 for (int i = viewCount - 1; i >= 0; i--)
3168 * Make new top and bottom frames. These take over the respective
3169 * AlignmentPanel objects, including their AlignmentViewports, so the
3170 * cdna/protein relationships between the viewports is carried over to the
3173 * explodedGeometry holds the (x, y) position of the previously exploded
3174 * SplitFrame, and the (width, height) of the AlignFrame component
3176 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3177 AlignFrame newTopFrame = new AlignFrame(topPanel);
3178 newTopFrame.setSize(oldTopFrame.getSize());
3179 newTopFrame.setVisible(true);
3180 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3181 .getExplodedGeometry();
3182 if (geometry != null)
3184 newTopFrame.setSize(geometry.getSize());
3187 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3188 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3189 newBottomFrame.setSize(oldBottomFrame.getSize());
3190 newBottomFrame.setVisible(true);
3191 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3192 .getExplodedGeometry();
3193 if (geometry != null)
3195 newBottomFrame.setSize(geometry.getSize());
3198 topPanel.av.setGatherViewsHere(false);
3199 bottomPanel.av.setGatherViewsHere(false);
3200 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3202 if (geometry != null)
3204 splitFrame.setLocation(geometry.getLocation());
3206 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3210 * Clear references to the panels (now relocated in the new SplitFrames)
3211 * before closing the old SplitFrame.
3214 bottomPanels.clear();
3219 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3220 * back into the given SplitFrame as additional views. Note that the gathered
3221 * frames may themselves have multiple views.
3225 public void gatherViews(GSplitFrame source)
3228 * special handling of explodedGeometry for a view within a SplitFrame: - it
3229 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3230 * height) of the AlignFrame component
3232 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3233 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3234 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3235 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3236 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3237 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3239 myTopFrame.viewport.setGatherViewsHere(true);
3240 myBottomFrame.viewport.setGatherViewsHere(true);
3241 String topViewId = myTopFrame.viewport.getSequenceSetId();
3242 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3244 JInternalFrame[] frames = desktop.getAllFrames();
3245 for (JInternalFrame frame : frames)
3247 if (frame instanceof SplitFrame && frame != source)
3249 SplitFrame sf = (SplitFrame) frame;
3250 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3251 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3252 boolean gatherThis = false;
3253 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3255 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3256 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3257 if (topViewId.equals(topPanel.av.getSequenceSetId())
3258 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3261 topPanel.av.setGatherViewsHere(false);
3262 bottomPanel.av.setGatherViewsHere(false);
3263 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3264 topFrame.getSize()));
3265 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3266 .getLocation(), bottomFrame.getSize()));
3267 myTopFrame.addAlignmentPanel(topPanel, false);
3268 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3274 topFrame.getAlignPanels().clear();
3275 bottomFrame.getAlignPanels().clear();
3282 * The dust settles...give focus to the tab we did this from.
3284 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3287 public static groovy.ui.Console getGroovyConsole()
3289 return groovyConsole;
3292 public static void transferFromDropTarget(List<String> files,
3293 List<String> protocols, DropTargetDropEvent evt, Transferable t)
3297 DataFlavor uriListFlavor = new DataFlavor(
3298 "text/uri-list;class=java.lang.String");
3299 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3301 // Works on Windows and MacOSX
3302 Cache.log.debug("Drop handled as javaFileListFlavor");
3303 for (Object file : (List) t
3304 .getTransferData(DataFlavor.javaFileListFlavor))
3306 files.add(((File) file).toString());
3307 protocols.add(FormatAdapter.FILE);
3312 // Unix like behaviour
3313 boolean added = false;
3315 if (t.isDataFlavorSupported(uriListFlavor))
3317 Cache.log.debug("Drop handled as uriListFlavor");
3318 // This is used by Unix drag system
3319 data = (String) t.getTransferData(uriListFlavor);
3323 // fallback to text: workaround - on OSX where there's a JVM bug
3324 Cache.log.debug("standard URIListFlavor failed. Trying text");
3325 // try text fallback
3326 data = (String) t.getTransferData(new DataFlavor(
3327 "text/plain;class=java.lang.String"));
3328 if (Cache.log.isDebugEnabled())
3330 Cache.log.debug("fallback returned " + data);
3333 while (protocols.size() < files.size())
3335 Cache.log.debug("Adding missing FILE protocol for "
3336 + files.get(protocols.size()));
3337 protocols.add(FormatAdapter.FILE);
3339 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3340 data, "\r\n"); st.hasMoreTokens();)
3343 String s = st.nextToken();
3344 if (s.startsWith("#"))
3346 // the line is a comment (as per the RFC 2483)
3349 java.net.URI uri = new java.net.URI(s);
3350 if (uri.getScheme().toLowerCase().startsWith("http"))
3352 protocols.add(FormatAdapter.URL);
3353 files.add(uri.toString());
3357 // otherwise preserve old behaviour: catch all for file objects
3358 java.io.File file = new java.io.File(uri);
3359 protocols.add(FormatAdapter.FILE);
3360 files.add(file.toString());
3363 if (Cache.log.isDebugEnabled())
3365 if (data == null || !added)
3368 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3369 for (DataFlavor fl : t.getTransferDataFlavors())
3371 Cache.log.debug("Supported transfer dataflavor: "
3373 Object df = t.getTransferData(fl);
3376 Cache.log.debug("Retrieves: " + df);
3380 Cache.log.debug("Retrieved nothing");