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.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.FocusEvent;
72 import java.awt.event.FocusListener;
73 import java.awt.event.KeyEvent;
74 import java.awt.event.MouseAdapter;
75 import java.awt.event.MouseEvent;
76 import java.awt.event.WindowAdapter;
77 import java.awt.event.WindowEvent;
78 import java.beans.PropertyChangeEvent;
79 import java.beans.PropertyChangeListener;
80 import java.io.BufferedInputStream;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Hashtable;
87 import java.util.List;
88 import java.util.ListIterator;
89 import java.util.StringTokenizer;
90 import java.util.Vector;
91 import java.util.concurrent.ExecutorService;
92 import java.util.concurrent.Executors;
93 import java.util.concurrent.Semaphore;
95 import javax.swing.AbstractAction;
96 import javax.swing.Box;
97 import javax.swing.BoxLayout;
98 import javax.swing.DefaultDesktopManager;
99 import javax.swing.DesktopManager;
100 import javax.swing.JButton;
101 import javax.swing.JCheckBox;
102 import javax.swing.JComboBox;
103 import javax.swing.JComponent;
104 import javax.swing.JDesktopPane;
105 import javax.swing.JFrame;
106 import javax.swing.JInternalFrame;
107 import javax.swing.JLabel;
108 import javax.swing.JMenuItem;
109 import javax.swing.JPanel;
110 import javax.swing.JPopupMenu;
111 import javax.swing.JProgressBar;
112 import javax.swing.KeyStroke;
113 import javax.swing.SwingUtilities;
114 import javax.swing.event.HyperlinkEvent;
115 import javax.swing.event.HyperlinkEvent.EventType;
116 import javax.swing.event.InternalFrameAdapter;
117 import javax.swing.event.InternalFrameEvent;
118 import javax.swing.event.MenuEvent;
119 import javax.swing.event.MenuListener;
126 * @version $Revision: 1.155 $
128 public class Desktop extends jalview.jbgui.GDesktop implements
129 DropTargetListener, ClipboardOwner, IProgressIndicator,
130 jalview.api.StructureSelectionManagerProvider
133 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
136 * news reader - null if it was never started.
138 private BlogReader jvnews = null;
140 private File projectFile;
144 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
146 public void addJalviewPropertyChangeListener(
147 PropertyChangeListener listener)
149 changeSupport.addJalviewPropertyChangeListener(listener);
153 * @param propertyName
155 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
156 * java.beans.PropertyChangeListener)
158 public void addJalviewPropertyChangeListener(String propertyName,
159 PropertyChangeListener listener)
161 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
165 * @param propertyName
167 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
168 * java.beans.PropertyChangeListener)
170 public void removeJalviewPropertyChangeListener(String propertyName,
171 PropertyChangeListener listener)
173 changeSupport.removeJalviewPropertyChangeListener(propertyName,
177 /** Singleton Desktop instance */
178 public static Desktop instance;
180 public static MyDesktopPane desktop;
182 static int openFrameCount = 0;
184 static final int xOffset = 30;
186 static final int yOffset = 30;
188 public static jalview.ws.jws1.Discoverer discoverer;
190 public static Object[] jalviewClipboard;
192 public static boolean internalCopy = false;
194 static int fileLoadingCount = 0;
196 class MyDesktopManager implements DesktopManager
199 private DesktopManager delegate;
201 public MyDesktopManager(DesktopManager delegate)
203 this.delegate = delegate;
207 public void activateFrame(JInternalFrame f)
211 delegate.activateFrame(f);
212 } catch (NullPointerException npe)
214 Point p = getMousePosition();
215 instance.showPasteMenu(p.x, p.y);
220 public void beginDraggingFrame(JComponent f)
222 delegate.beginDraggingFrame(f);
226 public void beginResizingFrame(JComponent f, int direction)
228 delegate.beginResizingFrame(f, direction);
232 public void closeFrame(JInternalFrame f)
234 delegate.closeFrame(f);
238 public void deactivateFrame(JInternalFrame f)
240 delegate.deactivateFrame(f);
244 public void deiconifyFrame(JInternalFrame f)
246 delegate.deiconifyFrame(f);
250 public void dragFrame(JComponent f, int newX, int newY)
256 delegate.dragFrame(f, newX, newY);
260 public void endDraggingFrame(JComponent f)
262 delegate.endDraggingFrame(f);
266 public void endResizingFrame(JComponent f)
268 delegate.endResizingFrame(f);
272 public void iconifyFrame(JInternalFrame f)
274 delegate.iconifyFrame(f);
278 public void maximizeFrame(JInternalFrame f)
280 delegate.maximizeFrame(f);
284 public void minimizeFrame(JInternalFrame f)
286 delegate.minimizeFrame(f);
290 public void openFrame(JInternalFrame f)
292 delegate.openFrame(f);
296 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
303 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
307 public void setBoundsForFrame(JComponent f, int newX, int newY,
308 int newWidth, int newHeight)
310 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
313 // All other methods, simply delegate
318 * Creates a new Desktop object.
323 * A note to implementors. It is ESSENTIAL that any activities that might
324 * block are spawned off as threads rather than waited for during this
328 doVamsasClientCheck();
330 groovyShell = new JMenuItem();
331 groovyShell.setText(MessageManager.getString("label.groovy_console"));
332 groovyShell.addActionListener(new ActionListener()
335 public void actionPerformed(ActionEvent e)
337 groovyShell_actionPerformed();
340 toolsMenu.add(groovyShell);
341 groovyShell.setVisible(true);
343 doConfigureStructurePrefs();
344 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
345 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
346 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
348 boolean showjconsole = jalview.bin.Cache.getDefault(
349 "SHOW_JAVA_CONSOLE", false);
350 desktop = new MyDesktopPane(selmemusage);
351 if (Platform.isAMac())
353 desktop.setDoubleBuffered(false);
355 showMemusage.setSelected(selmemusage);
356 desktop.setBackground(Color.white);
357 getContentPane().setLayout(new BorderLayout());
358 // alternate config - have scrollbars - see notes in JAL-153
359 // JScrollPane sp = new JScrollPane();
360 // sp.getViewport().setView(desktop);
361 // getContentPane().add(sp, BorderLayout.CENTER);
362 getContentPane().add(desktop, BorderLayout.CENTER);
363 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
365 // This line prevents Windows Look&Feel resizing all new windows to maximum
366 // if previous window was maximised
367 desktop.setDesktopManager(new MyDesktopManager(
368 new DefaultDesktopManager()));
370 Rectangle dims = getLastKnownDimensions("");
377 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
378 setBounds((screenSize.width - 900) / 2,
379 (screenSize.height - 650) / 2, 900, 650);
381 jconsole = new Console(this, showjconsole);
382 // add essential build information
383 jconsole.setHeader("Jalview Version: "
384 + jalview.bin.Cache.getProperty("VERSION") + "\n"
385 + "Jalview Installation: "
386 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
387 + "\n" + "Build Date: "
388 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
389 + "Java version: " + System.getProperty("java.version") + "\n"
390 + System.getProperty("os.arch") + " "
391 + System.getProperty("os.name") + " "
392 + System.getProperty("os.version"));
394 showConsole(showjconsole);
396 showNews.setVisible(false);
398 getIdentifiersOrgData();
402 this.addWindowListener(new WindowAdapter()
405 public void windowClosing(WindowEvent evt)
412 this.addMouseListener(ma = new MouseAdapter()
415 public void mousePressed(MouseEvent evt)
417 if (evt.isPopupTrigger()) // Mac
419 showPasteMenu(evt.getX(), evt.getY());
424 public void mouseReleased(MouseEvent evt)
426 if (evt.isPopupTrigger()) // Windows
428 showPasteMenu(evt.getX(), evt.getY());
432 desktop.addMouseListener(ma);
434 this.addFocusListener(new FocusListener()
438 public void focusLost(FocusEvent e)
440 // TODO Auto-generated method stub
445 public void focusGained(FocusEvent e)
447 Cache.log.debug("Relaying windows after focus gain");
448 // make sure that we sort windows properly after we gain focus
449 instance.relayerWindows();
452 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
453 // Spawn a thread that shows the splashscreen
454 SwingUtilities.invokeLater(new Runnable()
463 // Thread off a new instance of the file chooser - this reduces the time it
464 // takes to open it later on.
465 new Thread(new Runnable()
470 Cache.log.debug("Filechooser init thread started.");
471 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
472 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
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 FileFormatI format = new IdentifyFile().identify(file,
717 DataSourceType.PASTE);
719 new FileLoader().LoadFile(file, DataSourceType.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)
924 windowMenu.add(menuItem);
929 frame.setSelected(true);
930 frame.requestFocus();
931 } catch (java.beans.PropertyVetoException ve)
933 } catch (java.lang.ClassCastException cex)
936 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
942 public void lostOwnership(Clipboard clipboard, Transferable contents)
946 Desktop.jalviewClipboard = null;
949 internalCopy = false;
953 public void dragEnter(DropTargetDragEvent evt)
958 public void dragExit(DropTargetEvent evt)
963 public void dragOver(DropTargetDragEvent evt)
968 public void dropActionChanged(DropTargetDragEvent evt)
979 public void drop(DropTargetDropEvent evt)
981 boolean success = true;
982 // JAL-1552 - acceptDrop required before getTransferable call for
983 // Java's Transferable for native dnd
984 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
985 Transferable t = evt.getTransferable();
986 List<String> files = new ArrayList<String>();
987 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
991 Desktop.transferFromDropTarget(files, protocols, evt, t);
992 } catch (Exception e)
1002 for (int i = 0; i < files.size(); i++)
1004 String file = files.get(i).toString();
1005 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1007 FileFormatI format = null;
1009 if (file.endsWith(".jar"))
1011 format = FileFormat.Jalview;
1016 format = new IdentifyFile().identify(file, protocol);
1019 new FileLoader().LoadFile(file, protocol, format);
1022 } catch (Exception ex)
1027 evt.dropComplete(success); // need this to ensure input focus is properly
1028 // transfered to any new windows created
1038 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1040 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1041 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1042 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1044 chooser.setFileView(new JalviewFileView());
1045 chooser.setDialogTitle(MessageManager
1046 .getString("label.open_local_file"));
1047 chooser.setToolTipText(MessageManager.getString("action.open"));
1049 int value = chooser.showOpenDialog(this);
1051 if (value == JalviewFileChooser.APPROVE_OPTION)
1053 String choice = chooser.getSelectedFile().getPath();
1054 Cache.setProperty("LAST_DIRECTORY", chooser
1055 .getSelectedFile().getParent());
1057 FileFormatI format = chooser.getSelectedFormat();
1060 * Call IdentifyFile to verify the file contains what its extension implies.
1061 * Skip this step for dynamically added file formats, because
1062 * IdentifyFile does not know how to recognise them.
1064 if (FileFormats.getInstance().isIdentifiable(format))
1068 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1069 } catch (FileFormatException e)
1071 // format = null; //??
1075 if (viewport != null)
1077 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1082 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1094 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1096 // This construct allows us to have a wider textfield
1098 JLabel label = new JLabel(
1099 MessageManager.getString("label.input_file_url"));
1100 final JComboBox history = new JComboBox();
1102 JPanel panel = new JPanel(new GridLayout(2, 1));
1105 history.setPreferredSize(new Dimension(400, 20));
1106 history.setEditable(true);
1107 history.addItem("http://www.");
1109 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1113 if (historyItems != null)
1115 st = new StringTokenizer(historyItems, "\t");
1117 while (st.hasMoreTokens())
1119 history.addItem(st.nextElement());
1123 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1124 MessageManager.getString("label.input_alignment_from_url"),
1125 JvOptionPane.OK_CANCEL_OPTION);
1127 if (reply != JvOptionPane.OK_OPTION)
1132 String url = history.getSelectedItem().toString();
1134 if (url.toLowerCase().endsWith(".jar"))
1136 if (viewport != null)
1138 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1139 FileFormat.Jalview);
1143 new FileLoader().LoadFile(url, DataSourceType.URL,
1144 FileFormat.Jalview);
1149 FileFormatI format = null;
1152 format = new IdentifyFile().identify(url, DataSourceType.URL);
1153 } catch (FileFormatException e)
1155 // TODO revise error handling, distinguish between
1156 // URL not found and response not valid
1161 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1162 MessageManager.formatMessage("label.couldnt_locate",
1163 new Object[] { url }), MessageManager
1164 .getString("label.url_not_found"),
1165 JvOptionPane.WARNING_MESSAGE);
1170 if (viewport != null)
1173 .LoadFile(viewport, url, DataSourceType.URL, format);
1177 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1183 * Opens the CutAndPaste window for the user to paste an alignment in to
1186 * - if not null, the pasted alignment is added to the current
1187 * alignment; if null, to a new alignment window
1190 public void inputTextboxMenuItem_actionPerformed(
1191 AlignmentViewPanel viewPanel)
1193 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1194 cap.setForInput(viewPanel);
1195 Desktop.addInternalFrame(cap,
1196 MessageManager.getString("label.cut_paste_alignmen_file"),
1206 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1208 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1209 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1211 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1212 getBounds().y, getWidth(), getHeight()));
1214 if (jconsole != null)
1216 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1217 jconsole.stopConsole();
1221 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1224 if (dialogExecutor != null)
1226 dialogExecutor.shutdownNow();
1228 closeAll_actionPerformed(null);
1230 if (groovyConsole != null)
1232 // suppress a possible repeat prompt to save script
1233 groovyConsole.setDirty(false);
1234 groovyConsole.exit();
1239 private void storeLastKnownDimensions(String string, Rectangle jc)
1241 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1242 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1243 + " height:" + jc.height);
1245 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1246 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1247 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1248 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1258 public void aboutMenuItem_actionPerformed(ActionEvent e)
1260 // StringBuffer message = getAboutMessage(false);
1261 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1263 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1264 new Thread(new Runnable()
1269 new SplashScreen(true);
1274 public StringBuffer getAboutMessage(boolean shortv)
1276 StringBuffer message = new StringBuffer();
1277 message.append("<html>");
1280 message.append("<h1><strong>Version: "
1281 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1282 message.append("<strong>Last Updated: <em>"
1283 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1284 + "</em></strong>");
1290 message.append("<strong>Version "
1291 + jalview.bin.Cache.getProperty("VERSION")
1292 + "; last updated: "
1293 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1296 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1299 message.append("<br>...Checking latest version...</br>");
1301 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1302 .equals(jalview.bin.Cache.getProperty("VERSION")))
1304 boolean red = false;
1305 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1306 .indexOf("automated build") == -1)
1309 // Displayed when code version and jnlp version do not match and code
1310 // version is not a development build
1311 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1314 message.append("<br>!! Version "
1315 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1317 + " is available for download from "
1318 + jalview.bin.Cache.getDefault("www.jalview.org",
1319 "http://www.jalview.org") + " !!");
1322 message.append("</div>");
1325 message.append("<br>Authors: "
1327 .getDefault("AUTHORFNAMES",
1328 "The Jalview Authors (See AUTHORS file for current list)")
1329 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1330 + "<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"
1331 + "<br><br>If you use Jalview, please cite:"
1332 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1333 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1334 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1346 public void documentationMenuItem_actionPerformed(ActionEvent e)
1350 Help.showHelpWindow();
1351 } catch (Exception ex)
1357 public void closeAll_actionPerformed(ActionEvent e)
1359 // TODO show a progress bar while closing?
1360 JInternalFrame[] frames = desktop.getAllFrames();
1361 for (int i = 0; i < frames.length; i++)
1365 frames[i].setClosed(true);
1366 } catch (java.beans.PropertyVetoException ex)
1370 Jalview.setCurrentAlignFrame(null);
1371 System.out.println("ALL CLOSED");
1372 if (v_client != null)
1374 // TODO clear binding to vamsas document objects on close_all
1378 * reset state of singleton objects as appropriate (clear down session state
1379 * when all windows are closed)
1381 StructureSelectionManager ssm = StructureSelectionManager
1382 .getStructureSelectionManager(this);
1391 public void raiseRelated_actionPerformed(ActionEvent e)
1393 reorderAssociatedWindows(false, false);
1397 public void minimizeAssociated_actionPerformed(ActionEvent e)
1399 reorderAssociatedWindows(true, false);
1402 void closeAssociatedWindows()
1404 reorderAssociatedWindows(false, true);
1410 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1414 protected void garbageCollect_actionPerformed(ActionEvent e)
1416 // We simply collect the garbage
1417 jalview.bin.Cache.log.debug("Collecting garbage...");
1419 jalview.bin.Cache.log.debug("Finished garbage collection.");
1426 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1430 protected void showMemusage_actionPerformed(ActionEvent e)
1432 desktop.showMemoryUsage(showMemusage.isSelected());
1439 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1443 protected void showConsole_actionPerformed(ActionEvent e)
1445 showConsole(showConsole.isSelected());
1448 Console jconsole = null;
1451 * control whether the java console is visible or not
1455 void showConsole(boolean selected)
1457 showConsole.setSelected(selected);
1458 // TODO: decide if we should update properties file
1459 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1461 jconsole.setVisible(selected);
1464 void reorderAssociatedWindows(boolean minimize, boolean close)
1466 JInternalFrame[] frames = desktop.getAllFrames();
1467 if (frames == null || frames.length < 1)
1472 AlignmentViewport source = null, target = null;
1473 if (frames[0] instanceof AlignFrame)
1475 source = ((AlignFrame) frames[0]).getCurrentView();
1477 else if (frames[0] instanceof TreePanel)
1479 source = ((TreePanel) frames[0]).getViewPort();
1481 else if (frames[0] instanceof PCAPanel)
1483 source = ((PCAPanel) frames[0]).av;
1485 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1487 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1492 for (int i = 0; i < frames.length; i++)
1495 if (frames[i] == null)
1499 if (frames[i] instanceof AlignFrame)
1501 target = ((AlignFrame) frames[i]).getCurrentView();
1503 else if (frames[i] instanceof TreePanel)
1505 target = ((TreePanel) frames[i]).getViewPort();
1507 else if (frames[i] instanceof PCAPanel)
1509 target = ((PCAPanel) frames[i]).av;
1511 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1513 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1516 if (source == target)
1522 frames[i].setClosed(true);
1526 frames[i].setIcon(minimize);
1529 frames[i].toFront();
1533 } catch (java.beans.PropertyVetoException ex)
1548 protected void preferences_actionPerformed(ActionEvent e)
1560 public void saveState_actionPerformed(ActionEvent e)
1562 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1565 chooser.setFileView(new JalviewFileView());
1566 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1568 int value = chooser.showSaveDialog(this);
1570 if (value == JalviewFileChooser.APPROVE_OPTION)
1572 final Desktop me = this;
1573 final java.io.File choice = chooser.getSelectedFile();
1574 setProjectFile(choice);
1576 new Thread(new Runnable()
1581 // TODO: refactor to Jalview desktop session controller action.
1582 setProgressBar(MessageManager.formatMessage(
1583 "label.saving_jalview_project",
1584 new Object[] { choice.getName() }), choice.hashCode());
1585 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1586 choice.getParent());
1587 // TODO catch and handle errors for savestate
1588 // TODO prevent user from messing with the Desktop whilst we're saving
1591 new Jalview2XML().saveState(choice);
1592 } catch (OutOfMemoryError oom)
1594 new OOMWarning("Whilst saving current state to "
1595 + choice.getName(), oom);
1596 } catch (Exception ex)
1599 "Problems whilst trying to save to " + choice.getName(),
1601 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1602 "label.error_whilst_saving_current_state_to",
1603 new Object[] { choice.getName() }), MessageManager
1604 .getString("label.couldnt_save_project"),
1605 JvOptionPane.WARNING_MESSAGE);
1607 setProgressBar(null, choice.hashCode());
1613 private void setProjectFile(File choice)
1615 this.projectFile = choice;
1618 public File getProjectFile()
1620 return this.projectFile;
1630 public void loadState_actionPerformed(ActionEvent e)
1632 JalviewFileChooser chooser = new JalviewFileChooser(
1633 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1634 "jvp", "jar" }, new String[] { "Jalview Project",
1635 "Jalview Project (old)" }, "Jalview Project");
1636 chooser.setFileView(new JalviewFileView());
1637 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1639 int value = chooser.showOpenDialog(this);
1641 if (value == JalviewFileChooser.APPROVE_OPTION)
1643 final File selectedFile = chooser.getSelectedFile();
1644 setProjectFile(selectedFile);
1645 final String choice = selectedFile.getAbsolutePath();
1646 Cache.setProperty("LAST_DIRECTORY",
1647 selectedFile.getParent());
1648 new Thread(new Runnable()
1654 MessageManager.formatMessage(
1655 "label.loading_jalview_project",
1656 new Object[] { choice }), choice.hashCode());
1659 new Jalview2XML().loadJalviewAlign(choice);
1660 } catch (OutOfMemoryError oom)
1662 new OOMWarning("Whilst loading project from " + choice, oom);
1663 } catch (Exception ex)
1665 Cache.log.error("Problems whilst loading project from "
1667 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1669 "label.error_whilst_loading_project_from",
1670 new Object[] { choice }), MessageManager
1671 .getString("label.couldnt_load_project"),
1672 JvOptionPane.WARNING_MESSAGE);
1674 setProgressBar(null, choice.hashCode());
1681 public void inputSequence_actionPerformed(ActionEvent e)
1683 new SequenceFetcher(this);
1686 JPanel progressPanel;
1688 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1690 public void startLoading(final String fileName)
1692 if (fileLoadingCount == 0)
1694 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1695 "label.loading_file", new Object[] { fileName })));
1700 private JPanel addProgressPanel(String string)
1702 if (progressPanel == null)
1704 progressPanel = new JPanel(new GridLayout(1, 1));
1705 totalProgressCount = 0;
1706 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1708 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1709 JProgressBar progressBar = new JProgressBar();
1710 progressBar.setIndeterminate(true);
1712 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1714 thisprogress.add(progressBar, BorderLayout.CENTER);
1715 progressPanel.add(thisprogress);
1716 ((GridLayout) progressPanel.getLayout())
1717 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1718 ++totalProgressCount;
1719 instance.validate();
1720 return thisprogress;
1723 int totalProgressCount = 0;
1725 private void removeProgressPanel(JPanel progbar)
1727 if (progressPanel != null)
1729 synchronized (progressPanel)
1731 progressPanel.remove(progbar);
1732 GridLayout gl = (GridLayout) progressPanel.getLayout();
1733 gl.setRows(gl.getRows() - 1);
1734 if (--totalProgressCount < 1)
1736 this.getContentPane().remove(progressPanel);
1737 progressPanel = null;
1744 public void stopLoading()
1747 if (fileLoadingCount < 1)
1749 while (fileLoadingPanels.size() > 0)
1751 removeProgressPanel(fileLoadingPanels.remove(0));
1753 fileLoadingPanels.clear();
1754 fileLoadingCount = 0;
1759 public static int getViewCount(String alignmentId)
1761 AlignmentViewport[] aps = getViewports(alignmentId);
1762 return (aps == null) ? 0 : aps.length;
1767 * @param alignmentId
1768 * - if null, all sets are returned
1769 * @return all AlignmentPanels concerning the alignmentId sequence set
1771 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1773 if (Desktop.desktop == null)
1775 // no frames created and in headless mode
1776 // TODO: verify that frames are recoverable when in headless mode
1779 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1780 AlignFrame[] frames = getAlignFrames();
1785 for (AlignFrame af : frames)
1787 for (AlignmentPanel ap : af.alignPanels)
1789 if (alignmentId == null
1790 || alignmentId.equals(ap.av.getSequenceSetId()))
1796 if (aps.size() == 0)
1800 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1805 * get all the viewports on an alignment.
1807 * @param sequenceSetId
1808 * unique alignment id (may be null - all viewports returned in that
1810 * @return all viewports on the alignment bound to sequenceSetId
1812 public static AlignmentViewport[] getViewports(String sequenceSetId)
1814 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1815 if (desktop != null)
1817 AlignFrame[] frames = Desktop.getAlignFrames();
1819 for (AlignFrame afr : frames)
1821 if (sequenceSetId == null
1822 || afr.getViewport().getSequenceSetId()
1823 .equals(sequenceSetId))
1825 if (afr.alignPanels != null)
1827 for (AlignmentPanel ap : afr.alignPanels)
1829 if (sequenceSetId == null
1830 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1838 viewp.add(afr.getViewport());
1842 if (viewp.size() > 0)
1844 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1851 * Explode the views in the given frame into separate AlignFrame
1855 public static void explodeViews(AlignFrame af)
1857 int size = af.alignPanels.size();
1863 for (int i = 0; i < size; i++)
1865 AlignmentPanel ap = af.alignPanels.get(i);
1866 AlignFrame newaf = new AlignFrame(ap);
1869 * Restore the view's last exploded frame geometry if known. Multiple
1870 * views from one exploded frame share and restore the same (frame)
1871 * position and size.
1873 Rectangle geometry = ap.av.getExplodedGeometry();
1874 if (geometry != null)
1876 newaf.setBounds(geometry);
1879 ap.av.setGatherViewsHere(false);
1881 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1882 AlignFrame.DEFAULT_HEIGHT);
1885 af.alignPanels.clear();
1886 af.closeMenuItem_actionPerformed(true);
1891 * Gather expanded views (separate AlignFrame's) with the same sequence set
1892 * identifier back in to this frame as additional views, and close the
1893 * expanded views. Note the expanded frames may themselves have multiple
1894 * views. We take the lot.
1898 public void gatherViews(AlignFrame source)
1900 source.viewport.setGatherViewsHere(true);
1901 source.viewport.setExplodedGeometry(source.getBounds());
1902 JInternalFrame[] frames = desktop.getAllFrames();
1903 String viewId = source.viewport.getSequenceSetId();
1905 for (int t = 0; t < frames.length; t++)
1907 if (frames[t] instanceof AlignFrame && frames[t] != source)
1909 AlignFrame af = (AlignFrame) frames[t];
1910 boolean gatherThis = false;
1911 for (int a = 0; a < af.alignPanels.size(); a++)
1913 AlignmentPanel ap = af.alignPanels.get(a);
1914 if (viewId.equals(ap.av.getSequenceSetId()))
1917 ap.av.setGatherViewsHere(false);
1918 ap.av.setExplodedGeometry(af.getBounds());
1919 source.addAlignmentPanel(ap, false);
1925 af.alignPanels.clear();
1926 af.closeMenuItem_actionPerformed(true);
1933 jalview.gui.VamsasApplication v_client = null;
1936 public void vamsasImport_actionPerformed(ActionEvent e)
1938 if (v_client == null)
1940 // Load and try to start a session.
1941 JalviewFileChooser chooser = new JalviewFileChooser(
1942 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1944 chooser.setFileView(new JalviewFileView());
1945 chooser.setDialogTitle(MessageManager
1946 .getString("label.open_saved_vamsas_session"));
1947 chooser.setToolTipText(MessageManager
1948 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1950 int value = chooser.showOpenDialog(this);
1952 if (value == JalviewFileChooser.APPROVE_OPTION)
1954 String fle = chooser.getSelectedFile().toString();
1955 if (!vamsasImport(chooser.getSelectedFile()))
1958 .showInternalMessageDialog(
1960 MessageManager.formatMessage(
1961 "label.couldnt_import_as_vamsas_session",
1962 new Object[] { fle }),
1964 .getString("label.vamsas_document_import_failed"),
1965 JvOptionPane.ERROR_MESSAGE);
1971 jalview.bin.Cache.log
1972 .error("Implementation error - load session from a running session is not supported.");
1977 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1980 * @return true if import was a success and a session was started.
1982 public boolean vamsasImport(URL url)
1984 // TODO: create progress bar
1985 if (v_client != null)
1988 jalview.bin.Cache.log
1989 .error("Implementation error - load session from a running session is not supported.");
1995 // copy the URL content to a temporary local file
1996 // TODO: be a bit cleverer here with nio (?!)
1997 File file = File.createTempFile("vdocfromurl", ".vdj");
1998 FileOutputStream fos = new FileOutputStream(file);
1999 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2000 byte[] buffer = new byte[2048];
2002 while ((ln = bis.read(buffer)) > -1)
2004 fos.write(buffer, 0, ln);
2008 v_client = new jalview.gui.VamsasApplication(this, file,
2009 url.toExternalForm());
2010 } catch (Exception ex)
2012 jalview.bin.Cache.log.error(
2013 "Failed to create new vamsas session from contents of URL "
2017 setupVamsasConnectedGui();
2018 v_client.initial_update(); // TODO: thread ?
2019 return v_client.inSession();
2023 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2026 * @return true if import was a success and a session was started.
2028 public boolean vamsasImport(File file)
2030 if (v_client != null)
2033 jalview.bin.Cache.log
2034 .error("Implementation error - load session from a running session is not supported.");
2038 setProgressBar(MessageManager.formatMessage(
2039 "status.importing_vamsas_session_from",
2040 new Object[] { file.getName() }), file.hashCode());
2043 v_client = new jalview.gui.VamsasApplication(this, file, null);
2044 } catch (Exception ex)
2046 setProgressBar(MessageManager.formatMessage(
2047 "status.importing_vamsas_session_from",
2048 new Object[] { file.getName() }), file.hashCode());
2049 jalview.bin.Cache.log.error(
2050 "New vamsas session from existing session file failed:", ex);
2053 setupVamsasConnectedGui();
2054 v_client.initial_update(); // TODO: thread ?
2055 setProgressBar(MessageManager.formatMessage(
2056 "status.importing_vamsas_session_from",
2057 new Object[] { file.getName() }), file.hashCode());
2058 return v_client.inSession();
2061 public boolean joinVamsasSession(String mysesid)
2063 if (v_client != null)
2067 .getString("error.try_join_vamsas_session_another"));
2069 if (mysesid == null)
2072 MessageManager.getString("error.invalid_vamsas_session_id"));
2074 v_client = new VamsasApplication(this, mysesid);
2075 setupVamsasConnectedGui();
2076 v_client.initial_update();
2077 return (v_client.inSession());
2081 public void vamsasStart_actionPerformed(ActionEvent e)
2083 if (v_client == null)
2086 // we just start a default session for moment.
2088 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2089 * getProperty("LAST_DIRECTORY"));
2091 * chooser.setFileView(new JalviewFileView());
2092 * chooser.setDialogTitle("Load Vamsas file");
2093 * chooser.setToolTipText("Import");
2095 * int value = chooser.showOpenDialog(this);
2097 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2098 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2100 v_client = new VamsasApplication(this);
2101 setupVamsasConnectedGui();
2102 v_client.initial_update(); // TODO: thread ?
2106 // store current data in session.
2107 v_client.push_update(); // TODO: thread
2111 protected void setupVamsasConnectedGui()
2113 vamsasStart.setText(MessageManager.getString("label.session_update"));
2114 vamsasSave.setVisible(true);
2115 vamsasStop.setVisible(true);
2116 vamsasImport.setVisible(false); // Document import to existing session is
2117 // not possible for vamsas-client-1.0.
2120 protected void setupVamsasDisconnectedGui()
2122 vamsasSave.setVisible(false);
2123 vamsasStop.setVisible(false);
2124 vamsasImport.setVisible(true);
2125 vamsasStart.setText(MessageManager
2126 .getString("label.new_vamsas_session"));
2130 public void vamsasStop_actionPerformed(ActionEvent e)
2132 if (v_client != null)
2134 v_client.end_session();
2136 setupVamsasDisconnectedGui();
2140 protected void buildVamsasStMenu()
2142 if (v_client == null)
2144 String[] sess = null;
2147 sess = VamsasApplication.getSessionList();
2148 } catch (Exception e)
2150 jalview.bin.Cache.log.warn(
2151 "Problem getting current sessions list.", e);
2156 jalview.bin.Cache.log.debug("Got current sessions list: "
2157 + sess.length + " entries.");
2158 VamsasStMenu.removeAll();
2159 for (int i = 0; i < sess.length; i++)
2161 JMenuItem sessit = new JMenuItem();
2162 sessit.setText(sess[i]);
2163 sessit.setToolTipText(MessageManager.formatMessage(
2164 "label.connect_to_session", new Object[] { sess[i] }));
2165 final Desktop dsktp = this;
2166 final String mysesid = sess[i];
2167 sessit.addActionListener(new ActionListener()
2171 public void actionPerformed(ActionEvent e)
2173 if (dsktp.v_client == null)
2175 Thread rthr = new Thread(new Runnable()
2181 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2182 dsktp.setupVamsasConnectedGui();
2183 dsktp.v_client.initial_update();
2191 VamsasStMenu.add(sessit);
2193 // don't show an empty menu.
2194 VamsasStMenu.setVisible(sess.length > 0);
2199 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2200 VamsasStMenu.removeAll();
2201 VamsasStMenu.setVisible(false);
2206 // Not interested in the content. Just hide ourselves.
2207 VamsasStMenu.setVisible(false);
2212 public void vamsasSave_actionPerformed(ActionEvent e)
2214 if (v_client != null)
2216 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2217 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2220 chooser.setFileView(new JalviewFileView());
2221 chooser.setDialogTitle(MessageManager
2222 .getString("label.save_vamsas_document_archive"));
2224 int value = chooser.showSaveDialog(this);
2226 if (value == JalviewFileChooser.APPROVE_OPTION)
2228 java.io.File choice = chooser.getSelectedFile();
2229 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2230 "label.saving_vamsas_doc",
2231 new Object[] { choice.getName() }));
2232 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2233 String warnmsg = null;
2234 String warnttl = null;
2237 v_client.vclient.storeDocument(choice);
2240 warnttl = "Serious Problem saving Vamsas Document";
2241 warnmsg = ex.toString();
2242 jalview.bin.Cache.log.error("Error Whilst saving document to "
2245 } catch (Exception ex)
2247 warnttl = "Problem saving Vamsas Document.";
2248 warnmsg = ex.toString();
2249 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2253 removeProgressPanel(progpanel);
2254 if (warnmsg != null)
2256 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2258 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2264 JPanel vamUpdate = null;
2267 * hide vamsas user gui bits when a vamsas document event is being handled.
2270 * true to hide gui, false to reveal gui
2272 public void setVamsasUpdate(boolean b)
2274 Cache.log.debug("Setting gui for Vamsas update "
2275 + (b ? "in progress" : "finished"));
2277 if (vamUpdate != null)
2279 this.removeProgressPanel(vamUpdate);
2283 vamUpdate = this.addProgressPanel(MessageManager
2284 .getString("label.updating_vamsas_session"));
2286 vamsasStart.setVisible(!b);
2287 vamsasStop.setVisible(!b);
2288 vamsasSave.setVisible(!b);
2291 public JInternalFrame[] getAllFrames()
2293 return desktop.getAllFrames();
2297 * Checks the given url to see if it gives a response indicating that the user
2298 * should be informed of a new questionnaire.
2302 public void checkForQuestionnaire(String url)
2304 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2305 // javax.swing.SwingUtilities.invokeLater(jvq);
2306 new Thread(jvq).start();
2309 public void checkURLLinks()
2311 // Thread off the URL link checker
2312 addDialogThread(new Runnable()
2317 if (Cache.getDefault("CHECKURLLINKS", true))
2319 // check what the actual links are - if it's just the default don't
2320 // bother with the warning
2321 List<String> links = Preferences.sequenceUrlLinks
2324 // only need to check links if there is one with a
2325 // SEQUENCE_ID which is not the default EMBL_EBI link
2326 ListIterator<String> li = links.listIterator();
2327 boolean check = false;
2328 List<JLabel> urls = new ArrayList<JLabel>();
2329 while (li.hasNext())
2331 String link = li.next();
2332 if (link.contains(SEQUENCE_ID)
2333 && !link.equals(UrlConstants.DEFAULT_STRING))
2336 int barPos = link.indexOf("|");
2337 String urlMsg = barPos == -1 ? link : link.substring(0,
2338 barPos) + ": " + link.substring(barPos + 1);
2339 urls.add(new JLabel(urlMsg));
2347 // ask user to check in case URL links use old style tokens
2348 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2349 JPanel msgPanel = new JPanel();
2350 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2351 msgPanel.add(Box.createVerticalGlue());
2352 JLabel msg = new JLabel(
2354 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2355 JLabel msg2 = new JLabel(
2357 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2359 for (JLabel url : urls)
2365 final JCheckBox jcb = new JCheckBox(
2366 MessageManager.getString("label.do_not_display_again"));
2367 jcb.addActionListener(new ActionListener()
2370 public void actionPerformed(ActionEvent e)
2372 // update Cache settings for "don't show this again"
2373 boolean showWarningAgain = !jcb.isSelected();
2374 Cache.setProperty("CHECKURLLINKS",
2375 Boolean.valueOf(showWarningAgain).toString());
2380 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2382 .getString("label.SEQUENCE_ID_no_longer_used"),
2383 JvOptionPane.WARNING_MESSAGE);
2390 * Proxy class for JDesktopPane which optionally displays the current memory
2391 * usage and highlights the desktop area with a red bar if free memory runs
2396 public class MyDesktopPane extends JDesktopPane implements Runnable
2399 private static final float ONE_MB = 1048576f;
2401 boolean showMemoryUsage = false;
2405 java.text.NumberFormat df;
2407 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2410 public MyDesktopPane(boolean showMemoryUsage)
2412 showMemoryUsage(showMemoryUsage);
2415 public void showMemoryUsage(boolean showMemory)
2417 this.showMemoryUsage = showMemory;
2420 Thread worker = new Thread(this);
2425 public boolean isShowMemoryUsage()
2427 return showMemoryUsage;
2433 df = java.text.NumberFormat.getNumberInstance();
2434 df.setMaximumFractionDigits(2);
2435 runtime = Runtime.getRuntime();
2437 while (showMemoryUsage)
2441 maxMemory = runtime.maxMemory() / ONE_MB;
2442 allocatedMemory = runtime.totalMemory() / ONE_MB;
2443 freeMemory = runtime.freeMemory() / ONE_MB;
2444 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2446 percentUsage = (totalFreeMemory / maxMemory) * 100;
2448 // if (percentUsage < 20)
2450 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2452 // instance.set.setBorder(border1);
2455 // sleep after showing usage
2457 } catch (Exception ex)
2459 ex.printStackTrace();
2465 public void paintComponent(Graphics g)
2467 if (showMemoryUsage && g != null && df != null)
2469 if (percentUsage < 20)
2471 g.setColor(Color.red);
2473 FontMetrics fm = g.getFontMetrics();
2476 g.drawString(MessageManager.formatMessage(
2477 "label.memory_stats",
2478 new Object[] { df.format(totalFreeMemory),
2479 df.format(maxMemory), df.format(percentUsage) }), 10,
2480 getHeight() - fm.getHeight());
2487 * fixes stacking order after a modal dialog to ensure windows that should be
2488 * on top actually are
2490 public void relayerWindows()
2495 protected JMenuItem groovyShell;
2498 * Accessor method to quickly get all the AlignmentFrames loaded.
2500 * @return an array of AlignFrame, or null if none found
2502 public static AlignFrame[] getAlignFrames()
2504 if (Jalview.isHeadlessMode())
2506 // Desktop.desktop is null in headless mode
2507 return new AlignFrame[] { Jalview.currentAlignFrame };
2510 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2516 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2518 for (int i = frames.length - 1; i > -1; i--)
2520 if (frames[i] instanceof AlignFrame)
2522 avp.add((AlignFrame) frames[i]);
2524 else if (frames[i] instanceof SplitFrame)
2527 * Also check for a split frame containing an AlignFrame
2529 GSplitFrame sf = (GSplitFrame) frames[i];
2530 if (sf.getTopFrame() instanceof AlignFrame)
2532 avp.add((AlignFrame) sf.getTopFrame());
2534 if (sf.getBottomFrame() instanceof AlignFrame)
2536 avp.add((AlignFrame) sf.getBottomFrame());
2540 if (avp.size() == 0)
2544 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2549 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2553 public GStructureViewer[] getJmols()
2555 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2561 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2563 for (int i = frames.length - 1; i > -1; i--)
2565 if (frames[i] instanceof AppJmol)
2567 GStructureViewer af = (GStructureViewer) frames[i];
2571 if (avp.size() == 0)
2575 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2580 * Add Groovy Support to Jalview
2582 public void groovyShell_actionPerformed()
2586 openGroovyConsole();
2587 } catch (Exception ex)
2589 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2590 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2592 MessageManager.getString("label.couldnt_create_groovy_shell"),
2593 MessageManager.getString("label.groovy_support_failed"),
2594 JvOptionPane.ERROR_MESSAGE);
2599 * Open the Groovy console
2601 void openGroovyConsole()
2603 if (groovyConsole == null)
2605 groovyConsole = new groovy.ui.Console();
2606 groovyConsole.setVariable("Jalview", this);
2607 groovyConsole.run();
2610 * We allow only one console at a time, so that AlignFrame menu option
2611 * 'Calculate | Run Groovy script' is unambiguous.
2612 * Disable 'Groovy Console', and enable 'Run script', when the console is
2613 * opened, and the reverse when it is closed
2615 Window window = (Window) groovyConsole.getFrame();
2616 window.addWindowListener(new WindowAdapter()
2619 public void windowClosed(WindowEvent e)
2622 * rebind CMD-Q from Groovy Console to Jalview Quit
2625 enableExecuteGroovy(false);
2631 * show Groovy console window (after close and reopen)
2633 ((Window) groovyConsole.getFrame()).setVisible(true);
2636 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2637 * and disable opening a second console
2639 enableExecuteGroovy(true);
2643 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2644 * binding when opened
2646 protected void addQuitHandler()
2648 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2649 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2650 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2651 getRootPane().getActionMap().put("Quit", new AbstractAction()
2654 public void actionPerformed(ActionEvent e)
2662 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2665 * true if Groovy console is open
2667 public void enableExecuteGroovy(boolean enabled)
2670 * disable opening a second Groovy console
2671 * (or re-enable when the console is closed)
2673 groovyShell.setEnabled(!enabled);
2675 AlignFrame[] alignFrames = getAlignFrames();
2676 if (alignFrames != null)
2678 for (AlignFrame af : alignFrames)
2680 af.setGroovyEnabled(enabled);
2686 * Progress bars managed by the IProgressIndicator method.
2688 private Hashtable<Long, JPanel> progressBars;
2690 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2695 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2698 public void setProgressBar(String message, long id)
2700 if (progressBars == null)
2702 progressBars = new Hashtable<Long, JPanel>();
2703 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2706 if (progressBars.get(new Long(id)) != null)
2708 JPanel panel = progressBars.remove(new Long(id));
2709 if (progressBarHandlers.contains(new Long(id)))
2711 progressBarHandlers.remove(new Long(id));
2713 removeProgressPanel(panel);
2717 progressBars.put(new Long(id), addProgressPanel(message));
2724 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2725 * jalview.gui.IProgressIndicatorHandler)
2728 public void registerHandler(final long id,
2729 final IProgressIndicatorHandler handler)
2731 if (progressBarHandlers == null
2732 || !progressBars.containsKey(new Long(id)))
2736 .getString("error.call_setprogressbar_before_registering_handler"));
2738 progressBarHandlers.put(new Long(id), handler);
2739 final JPanel progressPanel = progressBars.get(new Long(id));
2740 if (handler.canCancel())
2742 JButton cancel = new JButton(
2743 MessageManager.getString("action.cancel"));
2744 final IProgressIndicator us = this;
2745 cancel.addActionListener(new ActionListener()
2749 public void actionPerformed(ActionEvent e)
2751 handler.cancelActivity(id);
2752 us.setProgressBar(MessageManager.formatMessage(
2753 "label.cancelled_params",
2754 new Object[] { ((JLabel) progressPanel.getComponent(0))
2758 progressPanel.add(cancel, BorderLayout.EAST);
2764 * @return true if any progress bars are still active
2767 public boolean operationInProgress()
2769 if (progressBars != null && progressBars.size() > 0)
2777 * This will return the first AlignFrame holding the given viewport instance.
2778 * It will break if there are more than one AlignFrames viewing a particular
2782 * @return alignFrame for viewport
2784 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2786 if (desktop != null)
2788 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2789 for (int panel = 0; aps != null && panel < aps.length; panel++)
2791 if (aps[panel] != null && aps[panel].av == viewport)
2793 return aps[panel].alignFrame;
2800 public VamsasApplication getVamsasApplication()
2807 * flag set if jalview GUI is being operated programmatically
2809 private boolean inBatchMode = false;
2812 * check if jalview GUI is being operated programmatically
2814 * @return inBatchMode
2816 public boolean isInBatchMode()
2822 * set flag if jalview GUI is being operated programmatically
2824 * @param inBatchMode
2826 public void setInBatchMode(boolean inBatchMode)
2828 this.inBatchMode = inBatchMode;
2831 public void startServiceDiscovery()
2833 startServiceDiscovery(false);
2836 public void startServiceDiscovery(boolean blocking)
2838 boolean alive = true;
2839 Thread t0 = null, t1 = null, t2 = null;
2840 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2843 // todo: changesupport handlers need to be transferred
2844 if (discoverer == null)
2846 discoverer = new jalview.ws.jws1.Discoverer();
2847 // register PCS handler for desktop.
2848 discoverer.addPropertyChangeListener(changeSupport);
2850 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2851 // until we phase out completely
2852 (t0 = new Thread(discoverer)).start();
2855 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2857 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2859 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2861 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2867 // TODO: do rest service discovery
2876 } catch (Exception e)
2879 alive = (t1 != null && t1.isAlive())
2880 || (t2 != null && t2.isAlive())
2881 || (t3 != null && t3.isAlive())
2882 || (t0 != null && t0.isAlive());
2888 * called to check if the service discovery process completed successfully.
2892 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2894 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2896 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2897 .getErrorMessages();
2900 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2902 if (serviceChangedDialog == null)
2904 // only run if we aren't already displaying one of these.
2905 addDialogThread(serviceChangedDialog = new Runnable()
2912 * JalviewDialog jd =new JalviewDialog() {
2914 * @Override protected void cancelPressed() { // TODO
2915 * Auto-generated method stub
2917 * }@Override protected void okPressed() { // TODO
2918 * Auto-generated method stub
2920 * }@Override protected void raiseClosed() { // TODO
2921 * Auto-generated method stub
2923 * } }; jd.initDialogFrame(new
2924 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2925 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2926 * + " or mis-configured HTTP proxy settings.<br/>" +
2927 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2929 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2930 * ), true, true, "Web Service Configuration Problem", 450,
2933 * jd.waitForInput();
2939 "<html><table width=\"450\"><tr><td>"
2941 + "</td></tr></table>"
2942 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2943 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2944 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2945 + " Tools->Preferences dialog box to change them.</p></html>"),
2946 "Web Service Configuration Problem",
2947 JvOptionPane.DEFAULT_OPTION,
2948 JvOptionPane.ERROR_MESSAGE);
2949 serviceChangedDialog = null;
2958 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2965 private Runnable serviceChangedDialog = null;
2968 * start a thread to open a URL in the configured browser. Pops up a warning
2969 * dialog to the user if there is an exception when calling out to the browser
2974 public static void showUrl(final String url)
2976 showUrl(url, Desktop.instance);
2980 * Like showUrl but allows progress handler to be specified
2984 * (null) or object implementing IProgressIndicator
2986 public static void showUrl(final String url,
2987 final IProgressIndicator progress)
2989 new Thread(new Runnable()
2996 if (progress != null)
2998 progress.setProgressBar(MessageManager.formatMessage(
2999 "status.opening_params", new Object[] { url }), this
3002 jalview.util.BrowserLauncher.openURL(url);
3003 } catch (Exception ex)
3005 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3007 .getString("label.web_browser_not_found_unix"),
3008 MessageManager.getString("label.web_browser_not_found"),
3009 JvOptionPane.WARNING_MESSAGE);
3011 ex.printStackTrace();
3013 if (progress != null)
3015 progress.setProgressBar(null, this.hashCode());
3021 public static WsParamSetManager wsparamManager = null;
3023 public static ParamManager getUserParameterStore()
3025 if (wsparamManager == null)
3027 wsparamManager = new WsParamSetManager();
3029 return wsparamManager;
3033 * static hyperlink handler proxy method for use by Jalview's internal windows
3037 public static void hyperlinkUpdate(HyperlinkEvent e)
3039 if (e.getEventType() == EventType.ACTIVATED)
3044 url = e.getURL().toString();
3045 Desktop.showUrl(url);
3046 } catch (Exception x)
3050 if (Cache.log != null)
3052 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3056 System.err.println("Couldn't handle string " + url
3060 // ignore any exceptions due to dud links.
3067 * single thread that handles display of dialogs to user.
3069 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3072 * flag indicating if dialogExecutor should try to acquire a permit
3074 private volatile boolean dialogPause = true;
3079 private java.util.concurrent.Semaphore block = new Semaphore(0);
3081 private static groovy.ui.Console groovyConsole;
3084 * add another dialog thread to the queue
3088 public void addDialogThread(final Runnable prompter)
3090 dialogExecutor.submit(new Runnable()
3100 } catch (InterruptedException x)
3105 if (instance == null)
3111 SwingUtilities.invokeAndWait(prompter);
3112 } catch (Exception q)
3114 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3120 public void startDialogQueue()
3122 // set the flag so we don't pause waiting for another permit and semaphore
3123 // the current task to begin
3124 dialogPause = false;
3129 protected void snapShotWindow_actionPerformed(ActionEvent e)
3133 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3134 "View of Desktop", getWidth(), getHeight(), of = new File(
3135 "Jalview_snapshot" + System.currentTimeMillis()
3136 + ".eps"), "View of desktop", null, 0, false);
3139 paintAll(im.getGraphics());
3141 } catch (Exception q)
3143 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3147 Cache.log.info("Successfully written snapshot to file "
3148 + of.getAbsolutePath());
3152 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3153 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3154 * and location last time the view was expanded (if any). However it does not
3155 * remember the split pane divider location - this is set to match the
3156 * 'exploding' frame.
3160 public void explodeViews(SplitFrame sf)
3162 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3163 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3164 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3166 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3168 int viewCount = topPanels.size();
3175 * Processing in reverse order works, forwards order leaves the first panels
3176 * not visible. I don't know why!
3178 for (int i = viewCount - 1; i >= 0; i--)
3181 * Make new top and bottom frames. These take over the respective
3182 * AlignmentPanel objects, including their AlignmentViewports, so the
3183 * cdna/protein relationships between the viewports is carried over to the
3186 * explodedGeometry holds the (x, y) position of the previously exploded
3187 * SplitFrame, and the (width, height) of the AlignFrame component
3189 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3190 AlignFrame newTopFrame = new AlignFrame(topPanel);
3191 newTopFrame.setSize(oldTopFrame.getSize());
3192 newTopFrame.setVisible(true);
3193 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3194 .getExplodedGeometry();
3195 if (geometry != null)
3197 newTopFrame.setSize(geometry.getSize());
3200 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3201 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3202 newBottomFrame.setSize(oldBottomFrame.getSize());
3203 newBottomFrame.setVisible(true);
3204 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3205 .getExplodedGeometry();
3206 if (geometry != null)
3208 newBottomFrame.setSize(geometry.getSize());
3211 topPanel.av.setGatherViewsHere(false);
3212 bottomPanel.av.setGatherViewsHere(false);
3213 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3215 if (geometry != null)
3217 splitFrame.setLocation(geometry.getLocation());
3219 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3223 * Clear references to the panels (now relocated in the new SplitFrames)
3224 * before closing the old SplitFrame.
3227 bottomPanels.clear();
3232 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3233 * back into the given SplitFrame as additional views. Note that the gathered
3234 * frames may themselves have multiple views.
3238 public void gatherViews(GSplitFrame source)
3241 * special handling of explodedGeometry for a view within a SplitFrame: - it
3242 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3243 * height) of the AlignFrame component
3245 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3246 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3247 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3248 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3249 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3250 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3252 myTopFrame.viewport.setGatherViewsHere(true);
3253 myBottomFrame.viewport.setGatherViewsHere(true);
3254 String topViewId = myTopFrame.viewport.getSequenceSetId();
3255 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3257 JInternalFrame[] frames = desktop.getAllFrames();
3258 for (JInternalFrame frame : frames)
3260 if (frame instanceof SplitFrame && frame != source)
3262 SplitFrame sf = (SplitFrame) frame;
3263 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3264 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3265 boolean gatherThis = false;
3266 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3268 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3269 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3270 if (topViewId.equals(topPanel.av.getSequenceSetId())
3271 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3274 topPanel.av.setGatherViewsHere(false);
3275 bottomPanel.av.setGatherViewsHere(false);
3276 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3277 topFrame.getSize()));
3278 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3279 .getLocation(), bottomFrame.getSize()));
3280 myTopFrame.addAlignmentPanel(topPanel, false);
3281 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3287 topFrame.getAlignPanels().clear();
3288 bottomFrame.getAlignPanels().clear();
3295 * The dust settles...give focus to the tab we did this from.
3297 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3300 public static groovy.ui.Console getGroovyConsole()
3302 return groovyConsole;
3305 public static void transferFromDropTarget(List<String> files,
3306 List<DataSourceType> protocols, DropTargetDropEvent evt,
3311 DataFlavor uriListFlavor = new DataFlavor(
3312 "text/uri-list;class=java.lang.String");
3313 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3315 // Works on Windows and MacOSX
3316 Cache.log.debug("Drop handled as javaFileListFlavor");
3317 for (Object file : (List) t
3318 .getTransferData(DataFlavor.javaFileListFlavor))
3320 files.add(((File) file).toString());
3321 protocols.add(DataSourceType.FILE);
3326 // Unix like behaviour
3327 boolean added = false;
3329 if (t.isDataFlavorSupported(uriListFlavor))
3331 Cache.log.debug("Drop handled as uriListFlavor");
3332 // This is used by Unix drag system
3333 data = (String) t.getTransferData(uriListFlavor);
3337 // fallback to text: workaround - on OSX where there's a JVM bug
3338 Cache.log.debug("standard URIListFlavor failed. Trying text");
3339 // try text fallback
3340 data = (String) t.getTransferData(new DataFlavor(
3341 "text/plain;class=java.lang.String"));
3342 if (Cache.log.isDebugEnabled())
3344 Cache.log.debug("fallback returned " + data);
3347 while (protocols.size() < files.size())
3349 Cache.log.debug("Adding missing FILE protocol for "
3350 + files.get(protocols.size()));
3351 protocols.add(DataSourceType.FILE);
3353 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3354 data, "\r\n"); st.hasMoreTokens();)
3357 String s = st.nextToken();
3358 if (s.startsWith("#"))
3360 // the line is a comment (as per the RFC 2483)
3363 java.net.URI uri = new java.net.URI(s);
3364 if (uri.getScheme().toLowerCase().startsWith("http"))
3366 protocols.add(DataSourceType.URL);
3367 files.add(uri.toString());
3371 // otherwise preserve old behaviour: catch all for file objects
3372 java.io.File file = new java.io.File(uri);
3373 protocols.add(DataSourceType.FILE);
3374 files.add(file.toString());
3377 if (Cache.log.isDebugEnabled())
3379 if (data == null || !added)
3382 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3383 for (DataFlavor fl : t.getTransferDataFlavors())
3385 Cache.log.debug("Supported transfer dataflavor: "
3387 Object df = t.getTransferData(fl);
3390 Cache.log.debug("Retrieves: " + df);
3394 Cache.log.debug("Retrieved nothing");