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
132 private static int DEFAULT_MIN_WIDTH = 300;
134 private static int DEFAULT_MIN_HEIGHT = 250;
136 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
139 * news reader - null if it was never started.
141 private BlogReader jvnews = null;
143 private File projectFile;
147 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
149 public void addJalviewPropertyChangeListener(
150 PropertyChangeListener listener)
152 changeSupport.addJalviewPropertyChangeListener(listener);
156 * @param propertyName
158 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
159 * java.beans.PropertyChangeListener)
161 public void addJalviewPropertyChangeListener(String propertyName,
162 PropertyChangeListener listener)
164 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
168 * @param propertyName
170 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
171 * java.beans.PropertyChangeListener)
173 public void removeJalviewPropertyChangeListener(String propertyName,
174 PropertyChangeListener listener)
176 changeSupport.removeJalviewPropertyChangeListener(propertyName,
180 /** Singleton Desktop instance */
181 public static Desktop instance;
183 public static MyDesktopPane desktop;
185 static int openFrameCount = 0;
187 static final int xOffset = 30;
189 static final int yOffset = 30;
191 public static jalview.ws.jws1.Discoverer discoverer;
193 public static Object[] jalviewClipboard;
195 public static boolean internalCopy = false;
197 static int fileLoadingCount = 0;
199 class MyDesktopManager implements DesktopManager
202 private DesktopManager delegate;
204 public MyDesktopManager(DesktopManager delegate)
206 this.delegate = delegate;
210 public void activateFrame(JInternalFrame f)
214 delegate.activateFrame(f);
215 } catch (NullPointerException npe)
217 Point p = getMousePosition();
218 instance.showPasteMenu(p.x, p.y);
223 public void beginDraggingFrame(JComponent f)
225 delegate.beginDraggingFrame(f);
229 public void beginResizingFrame(JComponent f, int direction)
231 delegate.beginResizingFrame(f, direction);
235 public void closeFrame(JInternalFrame f)
237 delegate.closeFrame(f);
241 public void deactivateFrame(JInternalFrame f)
243 delegate.deactivateFrame(f);
247 public void deiconifyFrame(JInternalFrame f)
249 delegate.deiconifyFrame(f);
253 public void dragFrame(JComponent f, int newX, int newY)
259 delegate.dragFrame(f, newX, newY);
263 public void endDraggingFrame(JComponent f)
265 delegate.endDraggingFrame(f);
269 public void endResizingFrame(JComponent f)
271 delegate.endResizingFrame(f);
275 public void iconifyFrame(JInternalFrame f)
277 delegate.iconifyFrame(f);
281 public void maximizeFrame(JInternalFrame f)
283 delegate.maximizeFrame(f);
287 public void minimizeFrame(JInternalFrame f)
289 delegate.minimizeFrame(f);
293 public void openFrame(JInternalFrame f)
295 delegate.openFrame(f);
299 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
306 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
310 public void setBoundsForFrame(JComponent f, int newX, int newY,
311 int newWidth, int newHeight)
313 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
316 // All other methods, simply delegate
321 * Creates a new Desktop object.
326 * A note to implementors. It is ESSENTIAL that any activities that might
327 * block are spawned off as threads rather than waited for during this
331 doVamsasClientCheck();
333 groovyShell = new JMenuItem();
334 groovyShell.setText(MessageManager.getString("label.groovy_console"));
335 groovyShell.addActionListener(new ActionListener()
338 public void actionPerformed(ActionEvent e)
340 groovyShell_actionPerformed();
343 toolsMenu.add(groovyShell);
344 groovyShell.setVisible(true);
346 doConfigureStructurePrefs();
347 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
348 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
349 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
351 boolean showjconsole = jalview.bin.Cache.getDefault(
352 "SHOW_JAVA_CONSOLE", false);
353 desktop = new MyDesktopPane(selmemusage);
354 if (Platform.isAMac())
356 desktop.setDoubleBuffered(false);
358 showMemusage.setSelected(selmemusage);
359 desktop.setBackground(Color.white);
360 getContentPane().setLayout(new BorderLayout());
361 // alternate config - have scrollbars - see notes in JAL-153
362 // JScrollPane sp = new JScrollPane();
363 // sp.getViewport().setView(desktop);
364 // getContentPane().add(sp, BorderLayout.CENTER);
365 getContentPane().add(desktop, BorderLayout.CENTER);
366 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
368 // This line prevents Windows Look&Feel resizing all new windows to maximum
369 // if previous window was maximised
370 desktop.setDesktopManager(new MyDesktopManager(
371 new DefaultDesktopManager()));
373 Rectangle dims = getLastKnownDimensions("");
380 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
381 setBounds((screenSize.width - 900) / 2,
382 (screenSize.height - 650) / 2, 900, 650);
384 jconsole = new Console(this, showjconsole);
385 // add essential build information
386 jconsole.setHeader("Jalview Version: "
387 + jalview.bin.Cache.getProperty("VERSION") + "\n"
388 + "Jalview Installation: "
389 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
390 + "\n" + "Build Date: "
391 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
392 + "Java version: " + System.getProperty("java.version") + "\n"
393 + System.getProperty("os.arch") + " "
394 + System.getProperty("os.name") + " "
395 + System.getProperty("os.version"));
397 showConsole(showjconsole);
399 showNews.setVisible(false);
401 getIdentifiersOrgData();
405 this.addWindowListener(new WindowAdapter()
408 public void windowClosing(WindowEvent evt)
415 this.addMouseListener(ma = new MouseAdapter()
418 public void mousePressed(MouseEvent evt)
420 if (evt.isPopupTrigger()) // Mac
422 showPasteMenu(evt.getX(), evt.getY());
427 public void mouseReleased(MouseEvent evt)
429 if (evt.isPopupTrigger()) // Windows
431 showPasteMenu(evt.getX(), evt.getY());
435 desktop.addMouseListener(ma);
437 this.addFocusListener(new FocusListener()
441 public void focusLost(FocusEvent e)
443 // TODO Auto-generated method stub
448 public void focusGained(FocusEvent e)
450 Cache.log.debug("Relaying windows after focus gain");
451 // make sure that we sort windows properly after we gain focus
452 instance.relayerWindows();
455 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
456 // Spawn a thread that shows the splashscreen
457 SwingUtilities.invokeLater(new Runnable()
466 // Thread off a new instance of the file chooser - this reduces the time it
467 // takes to open it later on.
468 new Thread(new Runnable()
473 Cache.log.debug("Filechooser init thread started.");
474 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
475 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
477 Cache.log.debug("Filechooser init thread finished.");
480 // Add the service change listener
481 changeSupport.addJalviewPropertyChangeListener("services",
482 new PropertyChangeListener()
486 public void propertyChange(PropertyChangeEvent evt)
488 Cache.log.debug("Firing service changed event for "
489 + evt.getNewValue());
490 JalviewServicesChanged(evt);
496 public void doConfigureStructurePrefs()
498 // configure services
499 StructureSelectionManager ssm = StructureSelectionManager
500 .getStructureSelectionManager(this);
501 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
503 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
504 Preferences.ADD_TEMPFACT_ANN, true));
505 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
506 Preferences.STRUCT_FROM_PDB, true));
507 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
508 Preferences.USE_RNAVIEW, true));
512 ssm.setAddTempFacAnnot(false);
513 ssm.setProcessSecondaryStructure(false);
514 ssm.setSecStructServices(false);
518 public void checkForNews()
520 final Desktop me = this;
521 // Thread off the news reader, in case there are connection problems.
522 addDialogThread(new Runnable()
527 Cache.log.debug("Starting news thread.");
529 jvnews = new BlogReader(me);
530 showNews.setVisible(true);
531 Cache.log.debug("Completed news thread.");
536 public void getIdentifiersOrgData()
538 // Thread off the identifiers fetcher
539 addDialogThread(new Runnable()
544 Cache.log.debug("Downloading data from identifiers.org");
545 UrlDownloadClient client = new UrlDownloadClient();
548 client.download(IdOrgSettings.getUrl(),
549 IdOrgSettings.getDownloadLocation());
550 } catch (IOException e)
552 Cache.log.debug("Exception downloading identifiers.org data"
560 protected void showNews_actionPerformed(ActionEvent e)
562 showNews(showNews.isSelected());
565 void showNews(boolean visible)
568 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
569 showNews.setSelected(visible);
570 if (visible && !jvnews.isVisible())
572 new Thread(new Runnable()
577 long now = System.currentTimeMillis();
578 Desktop.instance.setProgressBar(
579 MessageManager.getString("status.refreshing_news"), now);
580 jvnews.refreshNews();
581 Desktop.instance.setProgressBar(null, now);
590 * recover the last known dimensions for a jalview window
593 * - empty string is desktop, all other windows have unique prefix
594 * @return null or last known dimensions scaled to current geometry (if last
595 * window geom was known)
597 Rectangle getLastKnownDimensions(String windowName)
599 // TODO: lock aspect ratio for scaling desktop Bug #0058199
600 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
601 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
602 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
603 String width = jalview.bin.Cache.getProperty(windowName
605 String height = jalview.bin.Cache.getProperty(windowName
607 if ((x != null) && (y != null) && (width != null) && (height != null))
609 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
610 .parseInt(width), ih = Integer.parseInt(height);
611 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
613 // attempt #1 - try to cope with change in screen geometry - this
614 // version doesn't preserve original jv aspect ratio.
615 // take ratio of current screen size vs original screen size.
616 double sw = ((1f * screenSize.width) / (1f * Integer
617 .parseInt(jalview.bin.Cache
618 .getProperty("SCREENGEOMETRY_WIDTH"))));
619 double sh = ((1f * screenSize.height) / (1f * Integer
620 .parseInt(jalview.bin.Cache
621 .getProperty("SCREENGEOMETRY_HEIGHT"))));
622 // rescale the bounds depending upon the current screen geometry.
623 ix = (int) (ix * sw);
624 iw = (int) (iw * sw);
625 iy = (int) (iy * sh);
626 ih = (int) (ih * sh);
627 while (ix >= screenSize.width)
629 jalview.bin.Cache.log
630 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
631 ix -= screenSize.width;
633 while (iy >= screenSize.height)
635 jalview.bin.Cache.log
636 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
637 iy -= screenSize.height;
639 jalview.bin.Cache.log.debug("Got last known dimensions for "
640 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
643 // return dimensions for new instance
644 return new Rectangle(ix, iy, iw, ih);
649 private void doVamsasClientCheck()
651 if (jalview.bin.Cache.vamsasJarsPresent())
653 setupVamsasDisconnectedGui();
654 VamsasMenu.setVisible(true);
655 final Desktop us = this;
656 VamsasMenu.addMenuListener(new MenuListener()
658 // this listener remembers when the menu was first selected, and
659 // doesn't rebuild the session list until it has been cleared and
661 boolean refresh = true;
664 public void menuCanceled(MenuEvent e)
670 public void menuDeselected(MenuEvent e)
676 public void menuSelected(MenuEvent e)
680 us.buildVamsasStMenu();
685 vamsasStart.setVisible(true);
689 void showPasteMenu(int x, int y)
691 JPopupMenu popup = new JPopupMenu();
692 JMenuItem item = new JMenuItem(
693 MessageManager.getString("label.paste_new_window"));
694 item.addActionListener(new ActionListener()
697 public void actionPerformed(ActionEvent evt)
704 popup.show(this, x, y);
711 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
712 Transferable contents = c.getContents(this);
714 if (contents != null)
716 String file = (String) contents
717 .getTransferData(DataFlavor.stringFlavor);
719 FileFormatI format = new IdentifyFile().identify(file,
720 DataSourceType.PASTE);
722 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
725 } catch (Exception ex)
728 .println("Unable to paste alignment from system clipboard:\n"
734 * Adds and opens the given frame to the desktop
745 public static synchronized void addInternalFrame(
746 final JInternalFrame frame, String title, int w, int h)
748 addInternalFrame(frame, title, true, w, h, true);
752 * Add an internal frame to the Jalview desktop
759 * When true, display frame immediately, otherwise, caller must call
760 * setVisible themselves.
766 public static synchronized void addInternalFrame(
767 final JInternalFrame frame, String title, boolean makeVisible,
770 addInternalFrame(frame, title, makeVisible, w, h, true);
774 * Add an internal frame to the Jalview desktop and make it visible
787 public static synchronized void addInternalFrame(
788 final JInternalFrame frame, String title, int w, int h,
791 addInternalFrame(frame, title, true, w, h, resizable);
795 * Add an internal frame to the Jalview desktop
802 * When true, display frame immediately, otherwise, caller must call
803 * setVisible themselves.
811 public static synchronized void addInternalFrame(
812 final JInternalFrame frame, String title, boolean makeVisible,
813 int w, int h, boolean resizable)
816 // TODO: allow callers to determine X and Y position of frame (eg. via
818 // TODO: consider fixing method to update entries in the window submenu with
819 // the current window title
821 frame.setTitle(title);
822 if (frame.getWidth() < 1 || frame.getHeight() < 1)
826 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
827 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
828 // IF JALVIEW IS RUNNING HEADLESS
829 // ///////////////////////////////////////////////
831 || (System.getProperty("java.awt.headless") != null && System
832 .getProperty("java.awt.headless").equals("true")))
839 frame.setMinimumSize(new Dimension(DEFAULT_MIN_WIDTH,
840 DEFAULT_MIN_HEIGHT));
841 frame.setVisible(makeVisible);
842 frame.setClosable(true);
843 frame.setResizable(resizable);
844 frame.setMaximizable(resizable);
845 frame.setIconifiable(resizable);
846 if (Platform.isAMac())
848 frame.setIconifiable(false);
849 frame.setFrameIcon(null);
850 // frame.setDesktopIcon(null);
851 frame.setDoubleBuffered(false);
853 if (frame.getX() < 1 && frame.getY() < 1)
855 frame.setLocation(xOffset * openFrameCount, yOffset
856 * ((openFrameCount - 1) % 10) + yOffset);
860 * add an entry for the new frame in the Window menu
861 * (and remove it when the frame is closed)
863 final JMenuItem menuItem = new JMenuItem(title);
864 frame.addInternalFrameListener(new InternalFrameAdapter()
867 public void internalFrameActivated(InternalFrameEvent evt)
869 JInternalFrame itf = desktop.getSelectedFrame();
877 public void internalFrameClosed(InternalFrameEvent evt)
879 PaintRefresher.RemoveComponent(frame);
882 * defensive check to prevent frames being
883 * added half off the window
885 if (openFrameCount > 0)
891 * ensure no reference to alignFrame retained by menu item listener
893 if (menuItem.getActionListeners().length > 0)
895 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
897 windowMenu.remove(menuItem);
898 JInternalFrame itf = desktop.getSelectedFrame();
902 if (itf instanceof AlignFrame)
904 Jalview.setCurrentAlignFrame((AlignFrame) itf);
911 menuItem.addActionListener(new ActionListener()
914 public void actionPerformed(ActionEvent e)
918 frame.setSelected(true);
919 frame.setIcon(false);
920 } catch (java.beans.PropertyVetoException ex)
929 windowMenu.add(menuItem);
934 frame.setSelected(true);
935 frame.requestFocus();
936 } catch (java.beans.PropertyVetoException ve)
938 } catch (java.lang.ClassCastException cex)
941 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
947 public void lostOwnership(Clipboard clipboard, Transferable contents)
951 Desktop.jalviewClipboard = null;
954 internalCopy = false;
958 public void dragEnter(DropTargetDragEvent evt)
963 public void dragExit(DropTargetEvent evt)
968 public void dragOver(DropTargetDragEvent evt)
973 public void dropActionChanged(DropTargetDragEvent evt)
984 public void drop(DropTargetDropEvent evt)
986 boolean success = true;
987 // JAL-1552 - acceptDrop required before getTransferable call for
988 // Java's Transferable for native dnd
989 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
990 Transferable t = evt.getTransferable();
991 List<String> files = new ArrayList<String>();
992 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
996 Desktop.transferFromDropTarget(files, protocols, evt, t);
997 } catch (Exception e)
1007 for (int i = 0; i < files.size(); i++)
1009 String file = files.get(i).toString();
1010 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1012 FileFormatI format = null;
1014 if (file.endsWith(".jar"))
1016 format = FileFormat.Jalview;
1021 format = new IdentifyFile().identify(file, protocol);
1024 new FileLoader().LoadFile(file, protocol, format);
1027 } catch (Exception ex)
1032 evt.dropComplete(success); // need this to ensure input focus is properly
1033 // transfered to any new windows created
1043 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1045 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1046 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1047 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1049 chooser.setFileView(new JalviewFileView());
1050 chooser.setDialogTitle(MessageManager
1051 .getString("label.open_local_file"));
1052 chooser.setToolTipText(MessageManager.getString("action.open"));
1054 int value = chooser.showOpenDialog(this);
1056 if (value == JalviewFileChooser.APPROVE_OPTION)
1058 String choice = chooser.getSelectedFile().getPath();
1059 Cache.setProperty("LAST_DIRECTORY", chooser
1060 .getSelectedFile().getParent());
1062 FileFormatI format = chooser.getSelectedFormat();
1065 * Call IdentifyFile to verify the file contains what its extension implies.
1066 * Skip this step for dynamically added file formats, because
1067 * IdentifyFile does not know how to recognise them.
1069 if (FileFormats.getInstance().isIdentifiable(format))
1073 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1074 } catch (FileFormatException e)
1076 // format = null; //??
1080 if (viewport != null)
1082 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1087 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1099 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1101 // This construct allows us to have a wider textfield
1103 JLabel label = new JLabel(
1104 MessageManager.getString("label.input_file_url"));
1105 final JComboBox history = new JComboBox();
1107 JPanel panel = new JPanel(new GridLayout(2, 1));
1110 history.setPreferredSize(new Dimension(400, 20));
1111 history.setEditable(true);
1112 history.addItem("http://www.");
1114 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1118 if (historyItems != null)
1120 st = new StringTokenizer(historyItems, "\t");
1122 while (st.hasMoreTokens())
1124 history.addItem(st.nextElement());
1128 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1129 MessageManager.getString("label.input_alignment_from_url"),
1130 JvOptionPane.OK_CANCEL_OPTION);
1132 if (reply != JvOptionPane.OK_OPTION)
1137 String url = history.getSelectedItem().toString();
1139 if (url.toLowerCase().endsWith(".jar"))
1141 if (viewport != null)
1143 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1144 FileFormat.Jalview);
1148 new FileLoader().LoadFile(url, DataSourceType.URL,
1149 FileFormat.Jalview);
1154 FileFormatI format = null;
1157 format = new IdentifyFile().identify(url, DataSourceType.URL);
1158 } catch (FileFormatException e)
1160 // TODO revise error handling, distinguish between
1161 // URL not found and response not valid
1166 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1167 MessageManager.formatMessage("label.couldnt_locate",
1168 new Object[] { url }), MessageManager
1169 .getString("label.url_not_found"),
1170 JvOptionPane.WARNING_MESSAGE);
1175 if (viewport != null)
1178 .LoadFile(viewport, url, DataSourceType.URL, format);
1182 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1188 * Opens the CutAndPaste window for the user to paste an alignment in to
1191 * - if not null, the pasted alignment is added to the current
1192 * alignment; if null, to a new alignment window
1195 public void inputTextboxMenuItem_actionPerformed(
1196 AlignmentViewPanel viewPanel)
1198 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1199 cap.setForInput(viewPanel);
1200 Desktop.addInternalFrame(cap,
1201 MessageManager.getString("label.cut_paste_alignmen_file"),
1211 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1213 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1214 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1216 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1217 getBounds().y, getWidth(), getHeight()));
1219 if (jconsole != null)
1221 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1222 jconsole.stopConsole();
1226 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1229 if (dialogExecutor != null)
1231 dialogExecutor.shutdownNow();
1233 closeAll_actionPerformed(null);
1235 if (groovyConsole != null)
1237 // suppress a possible repeat prompt to save script
1238 groovyConsole.setDirty(false);
1239 groovyConsole.exit();
1244 private void storeLastKnownDimensions(String string, Rectangle jc)
1246 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1247 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1248 + " height:" + jc.height);
1250 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1251 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1252 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1253 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1263 public void aboutMenuItem_actionPerformed(ActionEvent e)
1265 // StringBuffer message = getAboutMessage(false);
1266 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1268 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1269 new Thread(new Runnable()
1274 new SplashScreen(true);
1279 public StringBuffer getAboutMessage(boolean shortv)
1281 StringBuffer message = new StringBuffer();
1282 message.append("<html>");
1285 message.append("<h1><strong>Version: "
1286 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1287 message.append("<strong>Last Updated: <em>"
1288 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1289 + "</em></strong>");
1295 message.append("<strong>Version "
1296 + jalview.bin.Cache.getProperty("VERSION")
1297 + "; last updated: "
1298 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1301 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1304 message.append("<br>...Checking latest version...</br>");
1306 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1307 .equals(jalview.bin.Cache.getProperty("VERSION")))
1309 boolean red = false;
1310 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1311 .indexOf("automated build") == -1)
1314 // Displayed when code version and jnlp version do not match and code
1315 // version is not a development build
1316 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1319 message.append("<br>!! Version "
1320 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1322 + " is available for download from "
1323 + jalview.bin.Cache.getDefault("www.jalview.org",
1324 "http://www.jalview.org") + " !!");
1327 message.append("</div>");
1330 message.append("<br>Authors: "
1332 .getDefault("AUTHORFNAMES",
1333 "The Jalview Authors (See AUTHORS file for current list)")
1334 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1335 + "<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"
1336 + "<br><br>If you use Jalview, please cite:"
1337 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1338 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1339 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1351 public void documentationMenuItem_actionPerformed(ActionEvent e)
1355 Help.showHelpWindow();
1356 } catch (Exception ex)
1362 public void closeAll_actionPerformed(ActionEvent e)
1364 // TODO show a progress bar while closing?
1365 JInternalFrame[] frames = desktop.getAllFrames();
1366 for (int i = 0; i < frames.length; i++)
1370 frames[i].setClosed(true);
1371 } catch (java.beans.PropertyVetoException ex)
1375 Jalview.setCurrentAlignFrame(null);
1376 System.out.println("ALL CLOSED");
1377 if (v_client != null)
1379 // TODO clear binding to vamsas document objects on close_all
1383 * reset state of singleton objects as appropriate (clear down session state
1384 * when all windows are closed)
1386 StructureSelectionManager ssm = StructureSelectionManager
1387 .getStructureSelectionManager(this);
1396 public void raiseRelated_actionPerformed(ActionEvent e)
1398 reorderAssociatedWindows(false, false);
1402 public void minimizeAssociated_actionPerformed(ActionEvent e)
1404 reorderAssociatedWindows(true, false);
1407 void closeAssociatedWindows()
1409 reorderAssociatedWindows(false, true);
1415 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1419 protected void garbageCollect_actionPerformed(ActionEvent e)
1421 // We simply collect the garbage
1422 jalview.bin.Cache.log.debug("Collecting garbage...");
1424 jalview.bin.Cache.log.debug("Finished garbage collection.");
1431 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1435 protected void showMemusage_actionPerformed(ActionEvent e)
1437 desktop.showMemoryUsage(showMemusage.isSelected());
1444 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1448 protected void showConsole_actionPerformed(ActionEvent e)
1450 showConsole(showConsole.isSelected());
1453 Console jconsole = null;
1456 * control whether the java console is visible or not
1460 void showConsole(boolean selected)
1462 showConsole.setSelected(selected);
1463 // TODO: decide if we should update properties file
1464 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1466 jconsole.setVisible(selected);
1469 void reorderAssociatedWindows(boolean minimize, boolean close)
1471 JInternalFrame[] frames = desktop.getAllFrames();
1472 if (frames == null || frames.length < 1)
1477 AlignmentViewport source = null, target = null;
1478 if (frames[0] instanceof AlignFrame)
1480 source = ((AlignFrame) frames[0]).getCurrentView();
1482 else if (frames[0] instanceof TreePanel)
1484 source = ((TreePanel) frames[0]).getViewPort();
1486 else if (frames[0] instanceof PCAPanel)
1488 source = ((PCAPanel) frames[0]).av;
1490 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1492 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1497 for (int i = 0; i < frames.length; i++)
1500 if (frames[i] == null)
1504 if (frames[i] instanceof AlignFrame)
1506 target = ((AlignFrame) frames[i]).getCurrentView();
1508 else if (frames[i] instanceof TreePanel)
1510 target = ((TreePanel) frames[i]).getViewPort();
1512 else if (frames[i] instanceof PCAPanel)
1514 target = ((PCAPanel) frames[i]).av;
1516 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1518 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1521 if (source == target)
1527 frames[i].setClosed(true);
1531 frames[i].setIcon(minimize);
1534 frames[i].toFront();
1538 } catch (java.beans.PropertyVetoException ex)
1553 protected void preferences_actionPerformed(ActionEvent e)
1565 public void saveState_actionPerformed(ActionEvent e)
1567 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1570 chooser.setFileView(new JalviewFileView());
1571 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1573 int value = chooser.showSaveDialog(this);
1575 if (value == JalviewFileChooser.APPROVE_OPTION)
1577 final Desktop me = this;
1578 final java.io.File choice = chooser.getSelectedFile();
1579 setProjectFile(choice);
1581 new Thread(new Runnable()
1586 // TODO: refactor to Jalview desktop session controller action.
1587 setProgressBar(MessageManager.formatMessage(
1588 "label.saving_jalview_project",
1589 new Object[] { choice.getName() }), choice.hashCode());
1590 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1591 choice.getParent());
1592 // TODO catch and handle errors for savestate
1593 // TODO prevent user from messing with the Desktop whilst we're saving
1596 new Jalview2XML().saveState(choice);
1597 } catch (OutOfMemoryError oom)
1599 new OOMWarning("Whilst saving current state to "
1600 + choice.getName(), oom);
1601 } catch (Exception ex)
1604 "Problems whilst trying to save to " + choice.getName(),
1606 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1607 "label.error_whilst_saving_current_state_to",
1608 new Object[] { choice.getName() }), MessageManager
1609 .getString("label.couldnt_save_project"),
1610 JvOptionPane.WARNING_MESSAGE);
1612 setProgressBar(null, choice.hashCode());
1618 private void setProjectFile(File choice)
1620 this.projectFile = choice;
1623 public File getProjectFile()
1625 return this.projectFile;
1635 public void loadState_actionPerformed(ActionEvent e)
1637 JalviewFileChooser chooser = new JalviewFileChooser(
1638 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1639 "jvp", "jar" }, new String[] { "Jalview Project",
1640 "Jalview Project (old)" }, "Jalview Project");
1641 chooser.setFileView(new JalviewFileView());
1642 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1644 int value = chooser.showOpenDialog(this);
1646 if (value == JalviewFileChooser.APPROVE_OPTION)
1648 final File selectedFile = chooser.getSelectedFile();
1649 setProjectFile(selectedFile);
1650 final String choice = selectedFile.getAbsolutePath();
1651 Cache.setProperty("LAST_DIRECTORY",
1652 selectedFile.getParent());
1653 new Thread(new Runnable()
1659 MessageManager.formatMessage(
1660 "label.loading_jalview_project",
1661 new Object[] { choice }), choice.hashCode());
1664 new Jalview2XML().loadJalviewAlign(choice);
1665 } catch (OutOfMemoryError oom)
1667 new OOMWarning("Whilst loading project from " + choice, oom);
1668 } catch (Exception ex)
1670 Cache.log.error("Problems whilst loading project from "
1672 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1674 "label.error_whilst_loading_project_from",
1675 new Object[] { choice }), MessageManager
1676 .getString("label.couldnt_load_project"),
1677 JvOptionPane.WARNING_MESSAGE);
1679 setProgressBar(null, choice.hashCode());
1686 public void inputSequence_actionPerformed(ActionEvent e)
1688 new SequenceFetcher(this);
1691 JPanel progressPanel;
1693 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1695 public void startLoading(final String fileName)
1697 if (fileLoadingCount == 0)
1699 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1700 "label.loading_file", new Object[] { fileName })));
1705 private JPanel addProgressPanel(String string)
1707 if (progressPanel == null)
1709 progressPanel = new JPanel(new GridLayout(1, 1));
1710 totalProgressCount = 0;
1711 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1713 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1714 JProgressBar progressBar = new JProgressBar();
1715 progressBar.setIndeterminate(true);
1717 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1719 thisprogress.add(progressBar, BorderLayout.CENTER);
1720 progressPanel.add(thisprogress);
1721 ((GridLayout) progressPanel.getLayout())
1722 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1723 ++totalProgressCount;
1724 instance.validate();
1725 return thisprogress;
1728 int totalProgressCount = 0;
1730 private void removeProgressPanel(JPanel progbar)
1732 if (progressPanel != null)
1734 synchronized (progressPanel)
1736 progressPanel.remove(progbar);
1737 GridLayout gl = (GridLayout) progressPanel.getLayout();
1738 gl.setRows(gl.getRows() - 1);
1739 if (--totalProgressCount < 1)
1741 this.getContentPane().remove(progressPanel);
1742 progressPanel = null;
1749 public void stopLoading()
1752 if (fileLoadingCount < 1)
1754 while (fileLoadingPanels.size() > 0)
1756 removeProgressPanel(fileLoadingPanels.remove(0));
1758 fileLoadingPanels.clear();
1759 fileLoadingCount = 0;
1764 public static int getViewCount(String alignmentId)
1766 AlignmentViewport[] aps = getViewports(alignmentId);
1767 return (aps == null) ? 0 : aps.length;
1772 * @param alignmentId
1773 * - if null, all sets are returned
1774 * @return all AlignmentPanels concerning the alignmentId sequence set
1776 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1778 if (Desktop.desktop == null)
1780 // no frames created and in headless mode
1781 // TODO: verify that frames are recoverable when in headless mode
1784 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1785 AlignFrame[] frames = getAlignFrames();
1790 for (AlignFrame af : frames)
1792 for (AlignmentPanel ap : af.alignPanels)
1794 if (alignmentId == null
1795 || alignmentId.equals(ap.av.getSequenceSetId()))
1801 if (aps.size() == 0)
1805 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1810 * get all the viewports on an alignment.
1812 * @param sequenceSetId
1813 * unique alignment id (may be null - all viewports returned in that
1815 * @return all viewports on the alignment bound to sequenceSetId
1817 public static AlignmentViewport[] getViewports(String sequenceSetId)
1819 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1820 if (desktop != null)
1822 AlignFrame[] frames = Desktop.getAlignFrames();
1824 for (AlignFrame afr : frames)
1826 if (sequenceSetId == null
1827 || afr.getViewport().getSequenceSetId()
1828 .equals(sequenceSetId))
1830 if (afr.alignPanels != null)
1832 for (AlignmentPanel ap : afr.alignPanels)
1834 if (sequenceSetId == null
1835 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1843 viewp.add(afr.getViewport());
1847 if (viewp.size() > 0)
1849 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1856 * Explode the views in the given frame into separate AlignFrame
1860 public static void explodeViews(AlignFrame af)
1862 int size = af.alignPanels.size();
1868 for (int i = 0; i < size; i++)
1870 AlignmentPanel ap = af.alignPanels.get(i);
1871 AlignFrame newaf = new AlignFrame(ap);
1874 * Restore the view's last exploded frame geometry if known. Multiple
1875 * views from one exploded frame share and restore the same (frame)
1876 * position and size.
1878 Rectangle geometry = ap.av.getExplodedGeometry();
1879 if (geometry != null)
1881 newaf.setBounds(geometry);
1884 ap.av.setGatherViewsHere(false);
1886 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1887 AlignFrame.DEFAULT_HEIGHT);
1890 af.alignPanels.clear();
1891 af.closeMenuItem_actionPerformed(true);
1896 * Gather expanded views (separate AlignFrame's) with the same sequence set
1897 * identifier back in to this frame as additional views, and close the
1898 * expanded views. Note the expanded frames may themselves have multiple
1899 * views. We take the lot.
1903 public void gatherViews(AlignFrame source)
1905 source.viewport.setGatherViewsHere(true);
1906 source.viewport.setExplodedGeometry(source.getBounds());
1907 JInternalFrame[] frames = desktop.getAllFrames();
1908 String viewId = source.viewport.getSequenceSetId();
1910 for (int t = 0; t < frames.length; t++)
1912 if (frames[t] instanceof AlignFrame && frames[t] != source)
1914 AlignFrame af = (AlignFrame) frames[t];
1915 boolean gatherThis = false;
1916 for (int a = 0; a < af.alignPanels.size(); a++)
1918 AlignmentPanel ap = af.alignPanels.get(a);
1919 if (viewId.equals(ap.av.getSequenceSetId()))
1922 ap.av.setGatherViewsHere(false);
1923 ap.av.setExplodedGeometry(af.getBounds());
1924 source.addAlignmentPanel(ap, false);
1930 af.alignPanels.clear();
1931 af.closeMenuItem_actionPerformed(true);
1938 jalview.gui.VamsasApplication v_client = null;
1941 public void vamsasImport_actionPerformed(ActionEvent e)
1943 if (v_client == null)
1945 // Load and try to start a session.
1946 JalviewFileChooser chooser = new JalviewFileChooser(
1947 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1949 chooser.setFileView(new JalviewFileView());
1950 chooser.setDialogTitle(MessageManager
1951 .getString("label.open_saved_vamsas_session"));
1952 chooser.setToolTipText(MessageManager
1953 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1955 int value = chooser.showOpenDialog(this);
1957 if (value == JalviewFileChooser.APPROVE_OPTION)
1959 String fle = chooser.getSelectedFile().toString();
1960 if (!vamsasImport(chooser.getSelectedFile()))
1963 .showInternalMessageDialog(
1965 MessageManager.formatMessage(
1966 "label.couldnt_import_as_vamsas_session",
1967 new Object[] { fle }),
1969 .getString("label.vamsas_document_import_failed"),
1970 JvOptionPane.ERROR_MESSAGE);
1976 jalview.bin.Cache.log
1977 .error("Implementation error - load session from a running session is not supported.");
1982 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1985 * @return true if import was a success and a session was started.
1987 public boolean vamsasImport(URL url)
1989 // TODO: create progress bar
1990 if (v_client != null)
1993 jalview.bin.Cache.log
1994 .error("Implementation error - load session from a running session is not supported.");
2000 // copy the URL content to a temporary local file
2001 // TODO: be a bit cleverer here with nio (?!)
2002 File file = File.createTempFile("vdocfromurl", ".vdj");
2003 FileOutputStream fos = new FileOutputStream(file);
2004 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2005 byte[] buffer = new byte[2048];
2007 while ((ln = bis.read(buffer)) > -1)
2009 fos.write(buffer, 0, ln);
2013 v_client = new jalview.gui.VamsasApplication(this, file,
2014 url.toExternalForm());
2015 } catch (Exception ex)
2017 jalview.bin.Cache.log.error(
2018 "Failed to create new vamsas session from contents of URL "
2022 setupVamsasConnectedGui();
2023 v_client.initial_update(); // TODO: thread ?
2024 return v_client.inSession();
2028 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2031 * @return true if import was a success and a session was started.
2033 public boolean vamsasImport(File file)
2035 if (v_client != null)
2038 jalview.bin.Cache.log
2039 .error("Implementation error - load session from a running session is not supported.");
2043 setProgressBar(MessageManager.formatMessage(
2044 "status.importing_vamsas_session_from",
2045 new Object[] { file.getName() }), file.hashCode());
2048 v_client = new jalview.gui.VamsasApplication(this, file, null);
2049 } catch (Exception ex)
2051 setProgressBar(MessageManager.formatMessage(
2052 "status.importing_vamsas_session_from",
2053 new Object[] { file.getName() }), file.hashCode());
2054 jalview.bin.Cache.log.error(
2055 "New vamsas session from existing session file failed:", ex);
2058 setupVamsasConnectedGui();
2059 v_client.initial_update(); // TODO: thread ?
2060 setProgressBar(MessageManager.formatMessage(
2061 "status.importing_vamsas_session_from",
2062 new Object[] { file.getName() }), file.hashCode());
2063 return v_client.inSession();
2066 public boolean joinVamsasSession(String mysesid)
2068 if (v_client != null)
2072 .getString("error.try_join_vamsas_session_another"));
2074 if (mysesid == null)
2077 MessageManager.getString("error.invalid_vamsas_session_id"));
2079 v_client = new VamsasApplication(this, mysesid);
2080 setupVamsasConnectedGui();
2081 v_client.initial_update();
2082 return (v_client.inSession());
2086 public void vamsasStart_actionPerformed(ActionEvent e)
2088 if (v_client == null)
2091 // we just start a default session for moment.
2093 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2094 * getProperty("LAST_DIRECTORY"));
2096 * chooser.setFileView(new JalviewFileView());
2097 * chooser.setDialogTitle("Load Vamsas file");
2098 * chooser.setToolTipText("Import");
2100 * int value = chooser.showOpenDialog(this);
2102 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2103 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2105 v_client = new VamsasApplication(this);
2106 setupVamsasConnectedGui();
2107 v_client.initial_update(); // TODO: thread ?
2111 // store current data in session.
2112 v_client.push_update(); // TODO: thread
2116 protected void setupVamsasConnectedGui()
2118 vamsasStart.setText(MessageManager.getString("label.session_update"));
2119 vamsasSave.setVisible(true);
2120 vamsasStop.setVisible(true);
2121 vamsasImport.setVisible(false); // Document import to existing session is
2122 // not possible for vamsas-client-1.0.
2125 protected void setupVamsasDisconnectedGui()
2127 vamsasSave.setVisible(false);
2128 vamsasStop.setVisible(false);
2129 vamsasImport.setVisible(true);
2130 vamsasStart.setText(MessageManager
2131 .getString("label.new_vamsas_session"));
2135 public void vamsasStop_actionPerformed(ActionEvent e)
2137 if (v_client != null)
2139 v_client.end_session();
2141 setupVamsasDisconnectedGui();
2145 protected void buildVamsasStMenu()
2147 if (v_client == null)
2149 String[] sess = null;
2152 sess = VamsasApplication.getSessionList();
2153 } catch (Exception e)
2155 jalview.bin.Cache.log.warn(
2156 "Problem getting current sessions list.", e);
2161 jalview.bin.Cache.log.debug("Got current sessions list: "
2162 + sess.length + " entries.");
2163 VamsasStMenu.removeAll();
2164 for (int i = 0; i < sess.length; i++)
2166 JMenuItem sessit = new JMenuItem();
2167 sessit.setText(sess[i]);
2168 sessit.setToolTipText(MessageManager.formatMessage(
2169 "label.connect_to_session", new Object[] { sess[i] }));
2170 final Desktop dsktp = this;
2171 final String mysesid = sess[i];
2172 sessit.addActionListener(new ActionListener()
2176 public void actionPerformed(ActionEvent e)
2178 if (dsktp.v_client == null)
2180 Thread rthr = new Thread(new Runnable()
2186 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2187 dsktp.setupVamsasConnectedGui();
2188 dsktp.v_client.initial_update();
2196 VamsasStMenu.add(sessit);
2198 // don't show an empty menu.
2199 VamsasStMenu.setVisible(sess.length > 0);
2204 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2205 VamsasStMenu.removeAll();
2206 VamsasStMenu.setVisible(false);
2211 // Not interested in the content. Just hide ourselves.
2212 VamsasStMenu.setVisible(false);
2217 public void vamsasSave_actionPerformed(ActionEvent e)
2219 if (v_client != null)
2221 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2222 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2225 chooser.setFileView(new JalviewFileView());
2226 chooser.setDialogTitle(MessageManager
2227 .getString("label.save_vamsas_document_archive"));
2229 int value = chooser.showSaveDialog(this);
2231 if (value == JalviewFileChooser.APPROVE_OPTION)
2233 java.io.File choice = chooser.getSelectedFile();
2234 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2235 "label.saving_vamsas_doc",
2236 new Object[] { choice.getName() }));
2237 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2238 String warnmsg = null;
2239 String warnttl = null;
2242 v_client.vclient.storeDocument(choice);
2245 warnttl = "Serious Problem saving Vamsas Document";
2246 warnmsg = ex.toString();
2247 jalview.bin.Cache.log.error("Error Whilst saving document to "
2250 } catch (Exception ex)
2252 warnttl = "Problem saving Vamsas Document.";
2253 warnmsg = ex.toString();
2254 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2258 removeProgressPanel(progpanel);
2259 if (warnmsg != null)
2261 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2263 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2269 JPanel vamUpdate = null;
2272 * hide vamsas user gui bits when a vamsas document event is being handled.
2275 * true to hide gui, false to reveal gui
2277 public void setVamsasUpdate(boolean b)
2279 Cache.log.debug("Setting gui for Vamsas update "
2280 + (b ? "in progress" : "finished"));
2282 if (vamUpdate != null)
2284 this.removeProgressPanel(vamUpdate);
2288 vamUpdate = this.addProgressPanel(MessageManager
2289 .getString("label.updating_vamsas_session"));
2291 vamsasStart.setVisible(!b);
2292 vamsasStop.setVisible(!b);
2293 vamsasSave.setVisible(!b);
2296 public JInternalFrame[] getAllFrames()
2298 return desktop.getAllFrames();
2302 * Checks the given url to see if it gives a response indicating that the user
2303 * should be informed of a new questionnaire.
2307 public void checkForQuestionnaire(String url)
2309 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2310 // javax.swing.SwingUtilities.invokeLater(jvq);
2311 new Thread(jvq).start();
2314 public void checkURLLinks()
2316 // Thread off the URL link checker
2317 addDialogThread(new Runnable()
2322 if (Cache.getDefault("CHECKURLLINKS", true))
2324 // check what the actual links are - if it's just the default don't
2325 // bother with the warning
2326 List<String> links = Preferences.sequenceUrlLinks
2329 // only need to check links if there is one with a
2330 // SEQUENCE_ID which is not the default EMBL_EBI link
2331 ListIterator<String> li = links.listIterator();
2332 boolean check = false;
2333 List<JLabel> urls = new ArrayList<JLabel>();
2334 while (li.hasNext())
2336 String link = li.next();
2337 if (link.contains(SEQUENCE_ID)
2338 && !link.equals(UrlConstants.DEFAULT_STRING))
2341 int barPos = link.indexOf("|");
2342 String urlMsg = barPos == -1 ? link : link.substring(0,
2343 barPos) + ": " + link.substring(barPos + 1);
2344 urls.add(new JLabel(urlMsg));
2352 // ask user to check in case URL links use old style tokens
2353 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2354 JPanel msgPanel = new JPanel();
2355 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2356 msgPanel.add(Box.createVerticalGlue());
2357 JLabel msg = new JLabel(
2359 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2360 JLabel msg2 = new JLabel(
2362 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2364 for (JLabel url : urls)
2370 final JCheckBox jcb = new JCheckBox(
2371 MessageManager.getString("label.do_not_display_again"));
2372 jcb.addActionListener(new ActionListener()
2375 public void actionPerformed(ActionEvent e)
2377 // update Cache settings for "don't show this again"
2378 boolean showWarningAgain = !jcb.isSelected();
2379 Cache.setProperty("CHECKURLLINKS",
2380 Boolean.valueOf(showWarningAgain).toString());
2385 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2387 .getString("label.SEQUENCE_ID_no_longer_used"),
2388 JvOptionPane.WARNING_MESSAGE);
2395 * Proxy class for JDesktopPane which optionally displays the current memory
2396 * usage and highlights the desktop area with a red bar if free memory runs
2401 public class MyDesktopPane extends JDesktopPane implements Runnable
2404 private static final float ONE_MB = 1048576f;
2406 boolean showMemoryUsage = false;
2410 java.text.NumberFormat df;
2412 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2415 public MyDesktopPane(boolean showMemoryUsage)
2417 showMemoryUsage(showMemoryUsage);
2420 public void showMemoryUsage(boolean showMemory)
2422 this.showMemoryUsage = showMemory;
2425 Thread worker = new Thread(this);
2430 public boolean isShowMemoryUsage()
2432 return showMemoryUsage;
2438 df = java.text.NumberFormat.getNumberInstance();
2439 df.setMaximumFractionDigits(2);
2440 runtime = Runtime.getRuntime();
2442 while (showMemoryUsage)
2446 maxMemory = runtime.maxMemory() / ONE_MB;
2447 allocatedMemory = runtime.totalMemory() / ONE_MB;
2448 freeMemory = runtime.freeMemory() / ONE_MB;
2449 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2451 percentUsage = (totalFreeMemory / maxMemory) * 100;
2453 // if (percentUsage < 20)
2455 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2457 // instance.set.setBorder(border1);
2460 // sleep after showing usage
2462 } catch (Exception ex)
2464 ex.printStackTrace();
2470 public void paintComponent(Graphics g)
2472 if (showMemoryUsage && g != null && df != null)
2474 if (percentUsage < 20)
2476 g.setColor(Color.red);
2478 FontMetrics fm = g.getFontMetrics();
2481 g.drawString(MessageManager.formatMessage(
2482 "label.memory_stats",
2483 new Object[] { df.format(totalFreeMemory),
2484 df.format(maxMemory), df.format(percentUsage) }), 10,
2485 getHeight() - fm.getHeight());
2492 * fixes stacking order after a modal dialog to ensure windows that should be
2493 * on top actually are
2495 public void relayerWindows()
2500 protected JMenuItem groovyShell;
2503 * Accessor method to quickly get all the AlignmentFrames loaded.
2505 * @return an array of AlignFrame, or null if none found
2507 public static AlignFrame[] getAlignFrames()
2509 if (Jalview.isHeadlessMode())
2511 // Desktop.desktop is null in headless mode
2512 return new AlignFrame[] { Jalview.currentAlignFrame };
2515 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2521 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2523 for (int i = frames.length - 1; i > -1; i--)
2525 if (frames[i] instanceof AlignFrame)
2527 avp.add((AlignFrame) frames[i]);
2529 else if (frames[i] instanceof SplitFrame)
2532 * Also check for a split frame containing an AlignFrame
2534 GSplitFrame sf = (GSplitFrame) frames[i];
2535 if (sf.getTopFrame() instanceof AlignFrame)
2537 avp.add((AlignFrame) sf.getTopFrame());
2539 if (sf.getBottomFrame() instanceof AlignFrame)
2541 avp.add((AlignFrame) sf.getBottomFrame());
2545 if (avp.size() == 0)
2549 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2554 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2558 public GStructureViewer[] getJmols()
2560 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2566 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2568 for (int i = frames.length - 1; i > -1; i--)
2570 if (frames[i] instanceof AppJmol)
2572 GStructureViewer af = (GStructureViewer) frames[i];
2576 if (avp.size() == 0)
2580 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2585 * Add Groovy Support to Jalview
2587 public void groovyShell_actionPerformed()
2591 openGroovyConsole();
2592 } catch (Exception ex)
2594 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2595 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2597 MessageManager.getString("label.couldnt_create_groovy_shell"),
2598 MessageManager.getString("label.groovy_support_failed"),
2599 JvOptionPane.ERROR_MESSAGE);
2604 * Open the Groovy console
2606 void openGroovyConsole()
2608 if (groovyConsole == null)
2610 groovyConsole = new groovy.ui.Console();
2611 groovyConsole.setVariable("Jalview", this);
2612 groovyConsole.run();
2615 * We allow only one console at a time, so that AlignFrame menu option
2616 * 'Calculate | Run Groovy script' is unambiguous.
2617 * Disable 'Groovy Console', and enable 'Run script', when the console is
2618 * opened, and the reverse when it is closed
2620 Window window = (Window) groovyConsole.getFrame();
2621 window.addWindowListener(new WindowAdapter()
2624 public void windowClosed(WindowEvent e)
2627 * rebind CMD-Q from Groovy Console to Jalview Quit
2630 enableExecuteGroovy(false);
2636 * show Groovy console window (after close and reopen)
2638 ((Window) groovyConsole.getFrame()).setVisible(true);
2641 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2642 * and disable opening a second console
2644 enableExecuteGroovy(true);
2648 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2649 * binding when opened
2651 protected void addQuitHandler()
2653 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2654 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2655 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2656 getRootPane().getActionMap().put("Quit", new AbstractAction()
2659 public void actionPerformed(ActionEvent e)
2667 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2670 * true if Groovy console is open
2672 public void enableExecuteGroovy(boolean enabled)
2675 * disable opening a second Groovy console
2676 * (or re-enable when the console is closed)
2678 groovyShell.setEnabled(!enabled);
2680 AlignFrame[] alignFrames = getAlignFrames();
2681 if (alignFrames != null)
2683 for (AlignFrame af : alignFrames)
2685 af.setGroovyEnabled(enabled);
2691 * Progress bars managed by the IProgressIndicator method.
2693 private Hashtable<Long, JPanel> progressBars;
2695 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2700 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2703 public void setProgressBar(String message, long id)
2705 if (progressBars == null)
2707 progressBars = new Hashtable<Long, JPanel>();
2708 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2711 if (progressBars.get(new Long(id)) != null)
2713 JPanel panel = progressBars.remove(new Long(id));
2714 if (progressBarHandlers.contains(new Long(id)))
2716 progressBarHandlers.remove(new Long(id));
2718 removeProgressPanel(panel);
2722 progressBars.put(new Long(id), addProgressPanel(message));
2729 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2730 * jalview.gui.IProgressIndicatorHandler)
2733 public void registerHandler(final long id,
2734 final IProgressIndicatorHandler handler)
2736 if (progressBarHandlers == null
2737 || !progressBars.containsKey(new Long(id)))
2741 .getString("error.call_setprogressbar_before_registering_handler"));
2743 progressBarHandlers.put(new Long(id), handler);
2744 final JPanel progressPanel = progressBars.get(new Long(id));
2745 if (handler.canCancel())
2747 JButton cancel = new JButton(
2748 MessageManager.getString("action.cancel"));
2749 final IProgressIndicator us = this;
2750 cancel.addActionListener(new ActionListener()
2754 public void actionPerformed(ActionEvent e)
2756 handler.cancelActivity(id);
2757 us.setProgressBar(MessageManager.formatMessage(
2758 "label.cancelled_params",
2759 new Object[] { ((JLabel) progressPanel.getComponent(0))
2763 progressPanel.add(cancel, BorderLayout.EAST);
2769 * @return true if any progress bars are still active
2772 public boolean operationInProgress()
2774 if (progressBars != null && progressBars.size() > 0)
2782 * This will return the first AlignFrame holding the given viewport instance.
2783 * It will break if there are more than one AlignFrames viewing a particular
2787 * @return alignFrame for viewport
2789 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2791 if (desktop != null)
2793 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2794 for (int panel = 0; aps != null && panel < aps.length; panel++)
2796 if (aps[panel] != null && aps[panel].av == viewport)
2798 return aps[panel].alignFrame;
2805 public VamsasApplication getVamsasApplication()
2812 * flag set if jalview GUI is being operated programmatically
2814 private boolean inBatchMode = false;
2817 * check if jalview GUI is being operated programmatically
2819 * @return inBatchMode
2821 public boolean isInBatchMode()
2827 * set flag if jalview GUI is being operated programmatically
2829 * @param inBatchMode
2831 public void setInBatchMode(boolean inBatchMode)
2833 this.inBatchMode = inBatchMode;
2836 public void startServiceDiscovery()
2838 startServiceDiscovery(false);
2841 public void startServiceDiscovery(boolean blocking)
2843 boolean alive = true;
2844 Thread t0 = null, t1 = null, t2 = null;
2845 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2848 // todo: changesupport handlers need to be transferred
2849 if (discoverer == null)
2851 discoverer = new jalview.ws.jws1.Discoverer();
2852 // register PCS handler for desktop.
2853 discoverer.addPropertyChangeListener(changeSupport);
2855 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2856 // until we phase out completely
2857 (t0 = new Thread(discoverer)).start();
2860 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2862 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");