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.FileLoader;
34 import jalview.io.IdentifyFile;
35 import jalview.io.JalviewFileChooser;
36 import jalview.io.JalviewFileView;
37 import jalview.jbgui.GSplitFrame;
38 import jalview.jbgui.GStructureViewer;
39 import jalview.structure.StructureSelectionManager;
40 import jalview.urls.IdOrgSettings;
41 import jalview.util.ImageMaker;
42 import jalview.util.MessageManager;
43 import jalview.util.Platform;
44 import jalview.util.UrlConstants;
45 import jalview.viewmodel.AlignmentViewport;
46 import jalview.ws.params.ParamManager;
47 import jalview.ws.utils.UrlDownloadClient;
49 import java.awt.BorderLayout;
50 import java.awt.Color;
51 import java.awt.Dimension;
52 import java.awt.FontMetrics;
53 import java.awt.Graphics;
54 import java.awt.GridLayout;
55 import java.awt.Point;
56 import java.awt.Rectangle;
57 import java.awt.Toolkit;
58 import java.awt.Window;
59 import java.awt.datatransfer.Clipboard;
60 import java.awt.datatransfer.ClipboardOwner;
61 import java.awt.datatransfer.DataFlavor;
62 import java.awt.datatransfer.Transferable;
63 import java.awt.dnd.DnDConstants;
64 import java.awt.dnd.DropTargetDragEvent;
65 import java.awt.dnd.DropTargetDropEvent;
66 import java.awt.dnd.DropTargetEvent;
67 import java.awt.dnd.DropTargetListener;
68 import java.awt.event.ActionEvent;
69 import java.awt.event.ActionListener;
70 import java.awt.event.FocusEvent;
71 import java.awt.event.FocusListener;
72 import java.awt.event.KeyEvent;
73 import java.awt.event.MouseAdapter;
74 import java.awt.event.MouseEvent;
75 import java.awt.event.WindowAdapter;
76 import java.awt.event.WindowEvent;
77 import java.beans.PropertyChangeEvent;
78 import java.beans.PropertyChangeListener;
79 import java.io.BufferedInputStream;
81 import java.io.FileOutputStream;
82 import java.io.IOException;
84 import java.util.ArrayList;
85 import java.util.Hashtable;
86 import java.util.List;
87 import java.util.ListIterator;
88 import java.util.StringTokenizer;
89 import java.util.Vector;
90 import java.util.concurrent.ExecutorService;
91 import java.util.concurrent.Executors;
92 import java.util.concurrent.Semaphore;
94 import javax.swing.AbstractAction;
95 import javax.swing.Box;
96 import javax.swing.BoxLayout;
97 import javax.swing.DefaultDesktopManager;
98 import javax.swing.DesktopManager;
99 import javax.swing.JButton;
100 import javax.swing.JCheckBox;
101 import javax.swing.JComboBox;
102 import javax.swing.JComponent;
103 import javax.swing.JDesktopPane;
104 import javax.swing.JFrame;
105 import javax.swing.JInternalFrame;
106 import javax.swing.JLabel;
107 import javax.swing.JMenuItem;
108 import javax.swing.JPanel;
109 import javax.swing.JPopupMenu;
110 import javax.swing.JProgressBar;
111 import javax.swing.KeyStroke;
112 import javax.swing.SwingUtilities;
113 import javax.swing.event.HyperlinkEvent;
114 import javax.swing.event.HyperlinkEvent.EventType;
115 import javax.swing.event.InternalFrameAdapter;
116 import javax.swing.event.InternalFrameEvent;
117 import javax.swing.event.MenuEvent;
118 import javax.swing.event.MenuListener;
125 * @version $Revision: 1.155 $
127 public class Desktop extends jalview.jbgui.GDesktop implements
128 DropTargetListener, ClipboardOwner, IProgressIndicator,
129 jalview.api.StructureSelectionManagerProvider
132 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
135 * news reader - null if it was never started.
137 private BlogReader jvnews = null;
139 private File projectFile;
143 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
145 public void addJalviewPropertyChangeListener(
146 PropertyChangeListener listener)
148 changeSupport.addJalviewPropertyChangeListener(listener);
152 * @param propertyName
154 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
155 * java.beans.PropertyChangeListener)
157 public void addJalviewPropertyChangeListener(String propertyName,
158 PropertyChangeListener listener)
160 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
164 * @param propertyName
166 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
167 * java.beans.PropertyChangeListener)
169 public void removeJalviewPropertyChangeListener(String propertyName,
170 PropertyChangeListener listener)
172 changeSupport.removeJalviewPropertyChangeListener(propertyName,
176 /** Singleton Desktop instance */
177 public static Desktop instance;
179 public static MyDesktopPane desktop;
181 static int openFrameCount = 0;
183 static final int xOffset = 30;
185 static final int yOffset = 30;
187 public static jalview.ws.jws1.Discoverer discoverer;
189 public static Object[] jalviewClipboard;
191 public static boolean internalCopy = false;
193 static int fileLoadingCount = 0;
195 class MyDesktopManager implements DesktopManager
198 private DesktopManager delegate;
200 public MyDesktopManager(DesktopManager delegate)
202 this.delegate = delegate;
206 public void activateFrame(JInternalFrame f)
210 delegate.activateFrame(f);
211 } catch (NullPointerException npe)
213 Point p = getMousePosition();
214 instance.showPasteMenu(p.x, p.y);
219 public void beginDraggingFrame(JComponent f)
221 delegate.beginDraggingFrame(f);
225 public void beginResizingFrame(JComponent f, int direction)
227 delegate.beginResizingFrame(f, direction);
231 public void closeFrame(JInternalFrame f)
233 delegate.closeFrame(f);
237 public void deactivateFrame(JInternalFrame f)
239 delegate.deactivateFrame(f);
243 public void deiconifyFrame(JInternalFrame f)
245 delegate.deiconifyFrame(f);
249 public void dragFrame(JComponent f, int newX, int newY)
255 delegate.dragFrame(f, newX, newY);
259 public void endDraggingFrame(JComponent f)
261 delegate.endDraggingFrame(f);
265 public void endResizingFrame(JComponent f)
267 delegate.endResizingFrame(f);
271 public void iconifyFrame(JInternalFrame f)
273 delegate.iconifyFrame(f);
277 public void maximizeFrame(JInternalFrame f)
279 delegate.maximizeFrame(f);
283 public void minimizeFrame(JInternalFrame f)
285 delegate.minimizeFrame(f);
289 public void openFrame(JInternalFrame f)
291 delegate.openFrame(f);
295 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
302 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
306 public void setBoundsForFrame(JComponent f, int newX, int newY,
307 int newWidth, int newHeight)
309 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
312 // All other methods, simply delegate
317 * Creates a new Desktop object.
322 * A note to implementors. It is ESSENTIAL that any activities that might
323 * block are spawned off as threads rather than waited for during this
327 doVamsasClientCheck();
329 groovyShell = new JMenuItem();
330 groovyShell.setText(MessageManager.getString("label.groovy_console"));
331 groovyShell.addActionListener(new ActionListener()
334 public void actionPerformed(ActionEvent e)
336 groovyShell_actionPerformed();
339 toolsMenu.add(groovyShell);
340 groovyShell.setVisible(true);
342 doConfigureStructurePrefs();
343 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
344 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
345 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
347 boolean showjconsole = jalview.bin.Cache.getDefault(
348 "SHOW_JAVA_CONSOLE", false);
349 desktop = new MyDesktopPane(selmemusage);
350 if (Platform.isAMac())
352 desktop.setDoubleBuffered(false);
354 showMemusage.setSelected(selmemusage);
355 desktop.setBackground(Color.white);
356 getContentPane().setLayout(new BorderLayout());
357 // alternate config - have scrollbars - see notes in JAL-153
358 // JScrollPane sp = new JScrollPane();
359 // sp.getViewport().setView(desktop);
360 // getContentPane().add(sp, BorderLayout.CENTER);
361 getContentPane().add(desktop, BorderLayout.CENTER);
362 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
364 // This line prevents Windows Look&Feel resizing all new windows to maximum
365 // if previous window was maximised
366 desktop.setDesktopManager(new MyDesktopManager(
367 new DefaultDesktopManager()));
369 Rectangle dims = getLastKnownDimensions("");
376 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
377 setBounds((screenSize.width - 900) / 2,
378 (screenSize.height - 650) / 2, 900, 650);
380 jconsole = new Console(this, showjconsole);
381 // add essential build information
382 jconsole.setHeader("Jalview Version: "
383 + jalview.bin.Cache.getProperty("VERSION") + "\n"
384 + "Jalview Installation: "
385 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
386 + "\n" + "Build Date: "
387 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
388 + "Java version: " + System.getProperty("java.version") + "\n"
389 + System.getProperty("os.arch") + " "
390 + System.getProperty("os.name") + " "
391 + System.getProperty("os.version"));
393 showConsole(showjconsole);
395 showNews.setVisible(false);
397 getIdentifiersOrgData();
401 this.addWindowListener(new WindowAdapter()
404 public void windowClosing(WindowEvent evt)
411 this.addMouseListener(ma = new MouseAdapter()
414 public void mousePressed(MouseEvent evt)
416 if (evt.isPopupTrigger()) // Mac
418 showPasteMenu(evt.getX(), evt.getY());
423 public void mouseReleased(MouseEvent evt)
425 if (evt.isPopupTrigger()) // Windows
427 showPasteMenu(evt.getX(), evt.getY());
431 desktop.addMouseListener(ma);
433 this.addFocusListener(new FocusListener()
437 public void focusLost(FocusEvent e)
439 // TODO Auto-generated method stub
444 public void focusGained(FocusEvent e)
446 Cache.log.debug("Relaying windows after focus gain");
447 // make sure that we sort windows properly after we gain focus
448 instance.relayerWindows();
451 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
452 // Spawn a thread that shows the splashscreen
453 SwingUtilities.invokeLater(new Runnable()
462 // Thread off a new instance of the file chooser - this reduces the time it
463 // takes to open it later on.
464 new Thread(new Runnable()
469 Cache.log.debug("Filechooser init thread started.");
470 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
471 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
473 Cache.log.debug("Filechooser init thread finished.");
476 // Add the service change listener
477 changeSupport.addJalviewPropertyChangeListener("services",
478 new PropertyChangeListener()
482 public void propertyChange(PropertyChangeEvent evt)
484 Cache.log.debug("Firing service changed event for "
485 + evt.getNewValue());
486 JalviewServicesChanged(evt);
492 public void doConfigureStructurePrefs()
494 // configure services
495 StructureSelectionManager ssm = StructureSelectionManager
496 .getStructureSelectionManager(this);
497 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
499 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
500 Preferences.ADD_TEMPFACT_ANN, true));
501 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
502 Preferences.STRUCT_FROM_PDB, true));
503 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
504 Preferences.USE_RNAVIEW, true));
508 ssm.setAddTempFacAnnot(false);
509 ssm.setProcessSecondaryStructure(false);
510 ssm.setSecStructServices(false);
514 public void checkForNews()
516 final Desktop me = this;
517 // Thread off the news reader, in case there are connection problems.
518 addDialogThread(new Runnable()
523 Cache.log.debug("Starting news thread.");
525 jvnews = new BlogReader(me);
526 showNews.setVisible(true);
527 Cache.log.debug("Completed news thread.");
532 public void getIdentifiersOrgData()
534 // Thread off the identifiers fetcher
535 addDialogThread(new Runnable()
540 Cache.log.debug("Downloading data from identifiers.org");
541 UrlDownloadClient client = new UrlDownloadClient();
544 client.download(IdOrgSettings.getUrl(),
545 IdOrgSettings.getDownloadLocation());
546 } catch (IOException e)
548 Cache.log.debug("Exception downloading identifiers.org data"
556 protected void showNews_actionPerformed(ActionEvent e)
558 showNews(showNews.isSelected());
561 void showNews(boolean visible)
564 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
565 showNews.setSelected(visible);
566 if (visible && !jvnews.isVisible())
568 new Thread(new Runnable()
573 long now = System.currentTimeMillis();
574 Desktop.instance.setProgressBar(
575 MessageManager.getString("status.refreshing_news"), now);
576 jvnews.refreshNews();
577 Desktop.instance.setProgressBar(null, now);
586 * recover the last known dimensions for a jalview window
589 * - empty string is desktop, all other windows have unique prefix
590 * @return null or last known dimensions scaled to current geometry (if last
591 * window geom was known)
593 Rectangle getLastKnownDimensions(String windowName)
595 // TODO: lock aspect ratio for scaling desktop Bug #0058199
596 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
597 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
598 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
599 String width = jalview.bin.Cache.getProperty(windowName
601 String height = jalview.bin.Cache.getProperty(windowName
603 if ((x != null) && (y != null) && (width != null) && (height != null))
605 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
606 .parseInt(width), ih = Integer.parseInt(height);
607 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
609 // attempt #1 - try to cope with change in screen geometry - this
610 // version doesn't preserve original jv aspect ratio.
611 // take ratio of current screen size vs original screen size.
612 double sw = ((1f * screenSize.width) / (1f * Integer
613 .parseInt(jalview.bin.Cache
614 .getProperty("SCREENGEOMETRY_WIDTH"))));
615 double sh = ((1f * screenSize.height) / (1f * Integer
616 .parseInt(jalview.bin.Cache
617 .getProperty("SCREENGEOMETRY_HEIGHT"))));
618 // rescale the bounds depending upon the current screen geometry.
619 ix = (int) (ix * sw);
620 iw = (int) (iw * sw);
621 iy = (int) (iy * sh);
622 ih = (int) (ih * sh);
623 while (ix >= screenSize.width)
625 jalview.bin.Cache.log
626 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
627 ix -= screenSize.width;
629 while (iy >= screenSize.height)
631 jalview.bin.Cache.log
632 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
633 iy -= screenSize.height;
635 jalview.bin.Cache.log.debug("Got last known dimensions for "
636 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
639 // return dimensions for new instance
640 return new Rectangle(ix, iy, iw, ih);
645 private void doVamsasClientCheck()
647 if (jalview.bin.Cache.vamsasJarsPresent())
649 setupVamsasDisconnectedGui();
650 VamsasMenu.setVisible(true);
651 final Desktop us = this;
652 VamsasMenu.addMenuListener(new MenuListener()
654 // this listener remembers when the menu was first selected, and
655 // doesn't rebuild the session list until it has been cleared and
657 boolean refresh = true;
660 public void menuCanceled(MenuEvent e)
666 public void menuDeselected(MenuEvent e)
672 public void menuSelected(MenuEvent e)
676 us.buildVamsasStMenu();
681 vamsasStart.setVisible(true);
685 void showPasteMenu(int x, int y)
687 JPopupMenu popup = new JPopupMenu();
688 JMenuItem item = new JMenuItem(
689 MessageManager.getString("label.paste_new_window"));
690 item.addActionListener(new ActionListener()
693 public void actionPerformed(ActionEvent evt)
700 popup.show(this, x, y);
707 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
708 Transferable contents = c.getContents(this);
710 if (contents != null)
712 String file = (String) contents
713 .getTransferData(DataFlavor.stringFlavor);
715 FileFormatI format = new IdentifyFile().identify(file,
716 DataSourceType.PASTE);
718 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
721 } catch (Exception ex)
724 .println("Unable to paste alignment from system clipboard:\n"
730 * Adds and opens the given frame to the desktop
741 public static synchronized void addInternalFrame(
742 final JInternalFrame frame, String title, int w, int h)
744 addInternalFrame(frame, title, true, w, h, true);
748 * Add an internal frame to the Jalview desktop
755 * When true, display frame immediately, otherwise, caller must call
756 * setVisible themselves.
762 public static synchronized void addInternalFrame(
763 final JInternalFrame frame, String title, boolean makeVisible,
766 addInternalFrame(frame, title, makeVisible, w, h, true);
770 * Add an internal frame to the Jalview desktop and make it visible
783 public static synchronized void addInternalFrame(
784 final JInternalFrame frame, String title, int w, int h,
787 addInternalFrame(frame, title, true, w, h, resizable);
791 * Add an internal frame to the Jalview desktop
798 * When true, display frame immediately, otherwise, caller must call
799 * setVisible themselves.
807 public static synchronized void addInternalFrame(
808 final JInternalFrame frame, String title, boolean makeVisible,
809 int w, int h, boolean resizable)
812 // TODO: allow callers to determine X and Y position of frame (eg. via
814 // TODO: consider fixing method to update entries in the window submenu with
815 // the current window title
817 frame.setTitle(title);
818 if (frame.getWidth() < 1 || frame.getHeight() < 1)
822 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
823 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
824 // IF JALVIEW IS RUNNING HEADLESS
825 // ///////////////////////////////////////////////
827 || (System.getProperty("java.awt.headless") != null && System
828 .getProperty("java.awt.headless").equals("true")))
835 frame.setVisible(makeVisible);
836 frame.setClosable(true);
837 frame.setResizable(resizable);
838 frame.setMaximizable(resizable);
839 frame.setIconifiable(resizable);
840 if (Platform.isAMac())
842 frame.setIconifiable(false);
843 frame.setFrameIcon(null);
844 // frame.setDesktopIcon(null);
845 frame.setDoubleBuffered(false);
847 if (frame.getX() < 1 && frame.getY() < 1)
849 frame.setLocation(xOffset * openFrameCount, yOffset
850 * ((openFrameCount - 1) % 10) + yOffset);
854 * add an entry for the new frame in the Window menu
855 * (and remove it when the frame is closed)
857 final JMenuItem menuItem = new JMenuItem(title);
858 frame.addInternalFrameListener(new InternalFrameAdapter()
861 public void internalFrameActivated(InternalFrameEvent evt)
863 JInternalFrame itf = desktop.getSelectedFrame();
871 public void internalFrameClosed(InternalFrameEvent evt)
873 PaintRefresher.RemoveComponent(frame);
876 * defensive check to prevent frames being
877 * added half off the window
879 if (openFrameCount > 0)
885 * ensure no reference to alignFrame retained by menu item listener
887 if (menuItem.getActionListeners().length > 0)
889 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
891 windowMenu.remove(menuItem);
892 JInternalFrame itf = desktop.getSelectedFrame();
896 if (itf instanceof AlignFrame)
898 Jalview.setCurrentAlignFrame((AlignFrame) itf);
905 menuItem.addActionListener(new ActionListener()
908 public void actionPerformed(ActionEvent e)
912 frame.setSelected(true);
913 frame.setIcon(false);
914 } catch (java.beans.PropertyVetoException ex)
923 windowMenu.add(menuItem);
928 frame.setSelected(true);
929 frame.requestFocus();
930 } catch (java.beans.PropertyVetoException ve)
932 } catch (java.lang.ClassCastException cex)
935 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
941 public void lostOwnership(Clipboard clipboard, Transferable contents)
945 Desktop.jalviewClipboard = null;
948 internalCopy = false;
952 public void dragEnter(DropTargetDragEvent evt)
957 public void dragExit(DropTargetEvent evt)
962 public void dragOver(DropTargetDragEvent evt)
967 public void dropActionChanged(DropTargetDragEvent evt)
978 public void drop(DropTargetDropEvent evt)
980 boolean success = true;
981 // JAL-1552 - acceptDrop required before getTransferable call for
982 // Java's Transferable for native dnd
983 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
984 Transferable t = evt.getTransferable();
985 List<String> files = new ArrayList<String>();
986 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
990 Desktop.transferFromDropTarget(files, protocols, evt, t);
991 } catch (Exception e)
1001 for (int i = 0; i < files.size(); i++)
1003 String file = files.get(i).toString();
1004 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1006 FileFormatI format = null;
1008 if (file.endsWith(".jar"))
1010 format = FileFormat.Jalview;
1015 format = new IdentifyFile().identify(file, protocol);
1018 new FileLoader().LoadFile(file, protocol, format);
1021 } catch (Exception ex)
1026 evt.dropComplete(success); // need this to ensure input focus is properly
1027 // transfered to any new windows created
1037 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1039 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1040 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1041 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1043 chooser.setFileView(new JalviewFileView());
1044 chooser.setDialogTitle(MessageManager
1045 .getString("label.open_local_file"));
1046 chooser.setToolTipText(MessageManager.getString("action.open"));
1048 int value = chooser.showOpenDialog(this);
1050 if (value == JalviewFileChooser.APPROVE_OPTION)
1052 String choice = chooser.getSelectedFile().getPath();
1053 Cache.setProperty("LAST_DIRECTORY", chooser
1054 .getSelectedFile().getParent());
1056 FileFormatI format = null;
1057 FileFormatI selectedFormat = chooser.getSelectedFormat();
1058 if (FileFormat.Jalview.equals(selectedFormat))
1060 format = FileFormat.Jalview;
1066 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1067 } catch (FileFormatException e)
1073 if (viewport != null)
1075 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1080 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1092 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1094 // This construct allows us to have a wider textfield
1096 JLabel label = new JLabel(
1097 MessageManager.getString("label.input_file_url"));
1098 final JComboBox history = new JComboBox();
1100 JPanel panel = new JPanel(new GridLayout(2, 1));
1103 history.setPreferredSize(new Dimension(400, 20));
1104 history.setEditable(true);
1105 history.addItem("http://www.");
1107 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1111 if (historyItems != null)
1113 st = new StringTokenizer(historyItems, "\t");
1115 while (st.hasMoreTokens())
1117 history.addItem(st.nextElement());
1121 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1122 MessageManager.getString("label.input_alignment_from_url"),
1123 JvOptionPane.OK_CANCEL_OPTION);
1125 if (reply != JvOptionPane.OK_OPTION)
1130 String url = history.getSelectedItem().toString();
1132 if (url.toLowerCase().endsWith(".jar"))
1134 if (viewport != null)
1136 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1137 FileFormat.Jalview);
1141 new FileLoader().LoadFile(url, DataSourceType.URL,
1142 FileFormat.Jalview);
1147 FileFormatI format = null;
1150 format = new IdentifyFile().identify(url, DataSourceType.URL);
1151 } catch (FileFormatException e)
1153 // TODO revise error handling, distinguish between
1154 // URL not found and response not valid
1159 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1160 MessageManager.formatMessage("label.couldnt_locate",
1161 new Object[] { url }), MessageManager
1162 .getString("label.url_not_found"),
1163 JvOptionPane.WARNING_MESSAGE);
1168 if (viewport != null)
1171 .LoadFile(viewport, url, DataSourceType.URL, format);
1175 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1181 * Opens the CutAndPaste window for the user to paste an alignment in to
1184 * - if not null, the pasted alignment is added to the current
1185 * alignment; if null, to a new alignment window
1188 public void inputTextboxMenuItem_actionPerformed(
1189 AlignmentViewPanel viewPanel)
1191 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1192 cap.setForInput(viewPanel);
1193 Desktop.addInternalFrame(cap,
1194 MessageManager.getString("label.cut_paste_alignmen_file"),
1204 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1206 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1207 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1209 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1210 getBounds().y, getWidth(), getHeight()));
1212 if (jconsole != null)
1214 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1215 jconsole.stopConsole();
1219 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1222 if (dialogExecutor != null)
1224 dialogExecutor.shutdownNow();
1226 closeAll_actionPerformed(null);
1228 if (groovyConsole != null)
1230 // suppress a possible repeat prompt to save script
1231 groovyConsole.setDirty(false);
1232 groovyConsole.exit();
1237 private void storeLastKnownDimensions(String string, Rectangle jc)
1239 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1240 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1241 + " height:" + jc.height);
1243 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1244 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1245 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1246 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1256 public void aboutMenuItem_actionPerformed(ActionEvent e)
1258 // StringBuffer message = getAboutMessage(false);
1259 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1261 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1262 new Thread(new Runnable()
1267 new SplashScreen(true);
1272 public StringBuffer getAboutMessage(boolean shortv)
1274 StringBuffer message = new StringBuffer();
1275 message.append("<html>");
1278 message.append("<h1><strong>Version: "
1279 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1280 message.append("<strong>Last Updated: <em>"
1281 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1282 + "</em></strong>");
1288 message.append("<strong>Version "
1289 + jalview.bin.Cache.getProperty("VERSION")
1290 + "; last updated: "
1291 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1294 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1297 message.append("<br>...Checking latest version...</br>");
1299 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1300 .equals(jalview.bin.Cache.getProperty("VERSION")))
1302 boolean red = false;
1303 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1304 .indexOf("automated build") == -1)
1307 // Displayed when code version and jnlp version do not match and code
1308 // version is not a development build
1309 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1312 message.append("<br>!! Version "
1313 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1315 + " is available for download from "
1316 + jalview.bin.Cache.getDefault("www.jalview.org",
1317 "http://www.jalview.org") + " !!");
1320 message.append("</div>");
1323 message.append("<br>Authors: "
1325 .getDefault("AUTHORFNAMES",
1326 "The Jalview Authors (See AUTHORS file for current list)")
1327 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1328 + "<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"
1329 + "<br><br>If you use Jalview, please cite:"
1330 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1331 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1332 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1344 public void documentationMenuItem_actionPerformed(ActionEvent e)
1348 Help.showHelpWindow();
1349 } catch (Exception ex)
1355 public void closeAll_actionPerformed(ActionEvent e)
1357 // TODO show a progress bar while closing?
1358 JInternalFrame[] frames = desktop.getAllFrames();
1359 for (int i = 0; i < frames.length; i++)
1363 frames[i].setClosed(true);
1364 } catch (java.beans.PropertyVetoException ex)
1368 Jalview.setCurrentAlignFrame(null);
1369 System.out.println("ALL CLOSED");
1370 if (v_client != null)
1372 // TODO clear binding to vamsas document objects on close_all
1376 * reset state of singleton objects as appropriate (clear down session state
1377 * when all windows are closed)
1379 StructureSelectionManager ssm = StructureSelectionManager
1380 .getStructureSelectionManager(this);
1389 public void raiseRelated_actionPerformed(ActionEvent e)
1391 reorderAssociatedWindows(false, false);
1395 public void minimizeAssociated_actionPerformed(ActionEvent e)
1397 reorderAssociatedWindows(true, false);
1400 void closeAssociatedWindows()
1402 reorderAssociatedWindows(false, true);
1408 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1412 protected void garbageCollect_actionPerformed(ActionEvent e)
1414 // We simply collect the garbage
1415 jalview.bin.Cache.log.debug("Collecting garbage...");
1417 jalview.bin.Cache.log.debug("Finished garbage collection.");
1424 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1428 protected void showMemusage_actionPerformed(ActionEvent e)
1430 desktop.showMemoryUsage(showMemusage.isSelected());
1437 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1441 protected void showConsole_actionPerformed(ActionEvent e)
1443 showConsole(showConsole.isSelected());
1446 Console jconsole = null;
1449 * control whether the java console is visible or not
1453 void showConsole(boolean selected)
1455 showConsole.setSelected(selected);
1456 // TODO: decide if we should update properties file
1457 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1459 jconsole.setVisible(selected);
1462 void reorderAssociatedWindows(boolean minimize, boolean close)
1464 JInternalFrame[] frames = desktop.getAllFrames();
1465 if (frames == null || frames.length < 1)
1470 AlignmentViewport source = null, target = null;
1471 if (frames[0] instanceof AlignFrame)
1473 source = ((AlignFrame) frames[0]).getCurrentView();
1475 else if (frames[0] instanceof TreePanel)
1477 source = ((TreePanel) frames[0]).getViewPort();
1479 else if (frames[0] instanceof PCAPanel)
1481 source = ((PCAPanel) frames[0]).av;
1483 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1485 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1490 for (int i = 0; i < frames.length; i++)
1493 if (frames[i] == null)
1497 if (frames[i] instanceof AlignFrame)
1499 target = ((AlignFrame) frames[i]).getCurrentView();
1501 else if (frames[i] instanceof TreePanel)
1503 target = ((TreePanel) frames[i]).getViewPort();
1505 else if (frames[i] instanceof PCAPanel)
1507 target = ((PCAPanel) frames[i]).av;
1509 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1511 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1514 if (source == target)
1520 frames[i].setClosed(true);
1524 frames[i].setIcon(minimize);
1527 frames[i].toFront();
1531 } catch (java.beans.PropertyVetoException ex)
1546 protected void preferences_actionPerformed(ActionEvent e)
1558 public void saveState_actionPerformed(ActionEvent e)
1560 JalviewFileChooser chooser = new JalviewFileChooser(
1561 Cache.getProperty("LAST_DIRECTORY"), "jvp", "Jalview Project");
1563 chooser.setFileView(new JalviewFileView());
1564 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1566 int value = chooser.showSaveDialog(this);
1568 if (value == JalviewFileChooser.APPROVE_OPTION)
1570 final Desktop me = this;
1571 final java.io.File choice = chooser.getSelectedFile();
1572 setProjectFile(choice);
1574 new Thread(new Runnable()
1579 // TODO: refactor to Jalview desktop session controller action.
1580 setProgressBar(MessageManager.formatMessage(
1581 "label.saving_jalview_project",
1582 new Object[] { choice.getName() }), choice.hashCode());
1583 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1584 choice.getParent());
1585 // TODO catch and handle errors for savestate
1586 // TODO prevent user from messing with the Desktop whilst we're saving
1589 new Jalview2XML().saveState(choice);
1590 } catch (OutOfMemoryError oom)
1592 new OOMWarning("Whilst saving current state to "
1593 + choice.getName(), oom);
1594 } catch (Exception ex)
1597 "Problems whilst trying to save to " + choice.getName(),
1599 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1600 "label.error_whilst_saving_current_state_to",
1601 new Object[] { choice.getName() }), MessageManager
1602 .getString("label.couldnt_save_project"),
1603 JvOptionPane.WARNING_MESSAGE);
1605 setProgressBar(null, choice.hashCode());
1611 private void setProjectFile(File choice)
1613 this.projectFile = choice;
1616 public File getProjectFile()
1618 return this.projectFile;
1628 public void loadState_actionPerformed(ActionEvent e)
1630 JalviewFileChooser chooser = new JalviewFileChooser(
1631 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1632 "jvp", "jar" }, new String[] { "Jalview Project",
1633 "Jalview Project (old)" }, "Jalview Project");
1634 chooser.setFileView(new JalviewFileView());
1635 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1637 int value = chooser.showOpenDialog(this);
1639 if (value == JalviewFileChooser.APPROVE_OPTION)
1641 final File selectedFile = chooser.getSelectedFile();
1642 setProjectFile(selectedFile);
1643 final String choice = selectedFile.getAbsolutePath();
1644 Cache.setProperty("LAST_DIRECTORY",
1645 selectedFile.getParent());
1646 new Thread(new Runnable()
1652 MessageManager.formatMessage(
1653 "label.loading_jalview_project",
1654 new Object[] { choice }), choice.hashCode());
1657 new Jalview2XML().loadJalviewAlign(choice);
1658 } catch (OutOfMemoryError oom)
1660 new OOMWarning("Whilst loading project from " + choice, oom);
1661 } catch (Exception ex)
1663 Cache.log.error("Problems whilst loading project from "
1665 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1667 "label.error_whilst_loading_project_from",
1668 new Object[] { choice }), MessageManager
1669 .getString("label.couldnt_load_project"),
1670 JvOptionPane.WARNING_MESSAGE);
1672 setProgressBar(null, choice.hashCode());
1679 public void inputSequence_actionPerformed(ActionEvent e)
1681 new SequenceFetcher(this);
1684 JPanel progressPanel;
1686 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1688 public void startLoading(final String fileName)
1690 if (fileLoadingCount == 0)
1692 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1693 "label.loading_file", new Object[] { fileName })));
1698 private JPanel addProgressPanel(String string)
1700 if (progressPanel == null)
1702 progressPanel = new JPanel(new GridLayout(1, 1));
1703 totalProgressCount = 0;
1704 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1706 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1707 JProgressBar progressBar = new JProgressBar();
1708 progressBar.setIndeterminate(true);
1710 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1712 thisprogress.add(progressBar, BorderLayout.CENTER);
1713 progressPanel.add(thisprogress);
1714 ((GridLayout) progressPanel.getLayout())
1715 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1716 ++totalProgressCount;
1717 instance.validate();
1718 return thisprogress;
1721 int totalProgressCount = 0;
1723 private void removeProgressPanel(JPanel progbar)
1725 if (progressPanel != null)
1727 synchronized (progressPanel)
1729 progressPanel.remove(progbar);
1730 GridLayout gl = (GridLayout) progressPanel.getLayout();
1731 gl.setRows(gl.getRows() - 1);
1732 if (--totalProgressCount < 1)
1734 this.getContentPane().remove(progressPanel);
1735 progressPanel = null;
1742 public void stopLoading()
1745 if (fileLoadingCount < 1)
1747 while (fileLoadingPanels.size() > 0)
1749 removeProgressPanel(fileLoadingPanels.remove(0));
1751 fileLoadingPanels.clear();
1752 fileLoadingCount = 0;
1757 public static int getViewCount(String alignmentId)
1759 AlignmentViewport[] aps = getViewports(alignmentId);
1760 return (aps == null) ? 0 : aps.length;
1765 * @param alignmentId
1766 * - if null, all sets are returned
1767 * @return all AlignmentPanels concerning the alignmentId sequence set
1769 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1771 if (Desktop.desktop == null)
1773 // no frames created and in headless mode
1774 // TODO: verify that frames are recoverable when in headless mode
1777 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1778 AlignFrame[] frames = getAlignFrames();
1783 for (AlignFrame af : frames)
1785 for (AlignmentPanel ap : af.alignPanels)
1787 if (alignmentId == null
1788 || alignmentId.equals(ap.av.getSequenceSetId()))
1794 if (aps.size() == 0)
1798 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1803 * get all the viewports on an alignment.
1805 * @param sequenceSetId
1806 * unique alignment id (may be null - all viewports returned in that
1808 * @return all viewports on the alignment bound to sequenceSetId
1810 public static AlignmentViewport[] getViewports(String sequenceSetId)
1812 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1813 if (desktop != null)
1815 AlignFrame[] frames = Desktop.getAlignFrames();
1817 for (AlignFrame afr : frames)
1819 if (sequenceSetId == null
1820 || afr.getViewport().getSequenceSetId()
1821 .equals(sequenceSetId))
1823 if (afr.alignPanels != null)
1825 for (AlignmentPanel ap : afr.alignPanels)
1827 if (sequenceSetId == null
1828 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1836 viewp.add(afr.getViewport());
1840 if (viewp.size() > 0)
1842 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1849 * Explode the views in the given frame into separate AlignFrame
1853 public static void explodeViews(AlignFrame af)
1855 int size = af.alignPanels.size();
1861 for (int i = 0; i < size; i++)
1863 AlignmentPanel ap = af.alignPanels.get(i);
1864 AlignFrame newaf = new AlignFrame(ap);
1867 * Restore the view's last exploded frame geometry if known. Multiple
1868 * views from one exploded frame share and restore the same (frame)
1869 * position and size.
1871 Rectangle geometry = ap.av.getExplodedGeometry();
1872 if (geometry != null)
1874 newaf.setBounds(geometry);
1877 ap.av.setGatherViewsHere(false);
1879 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1880 AlignFrame.DEFAULT_HEIGHT);
1883 af.alignPanels.clear();
1884 af.closeMenuItem_actionPerformed(true);
1889 * Gather expanded views (separate AlignFrame's) with the same sequence set
1890 * identifier back in to this frame as additional views, and close the
1891 * expanded views. Note the expanded frames may themselves have multiple
1892 * views. We take the lot.
1896 public void gatherViews(AlignFrame source)
1898 source.viewport.setGatherViewsHere(true);
1899 source.viewport.setExplodedGeometry(source.getBounds());
1900 JInternalFrame[] frames = desktop.getAllFrames();
1901 String viewId = source.viewport.getSequenceSetId();
1903 for (int t = 0; t < frames.length; t++)
1905 if (frames[t] instanceof AlignFrame && frames[t] != source)
1907 AlignFrame af = (AlignFrame) frames[t];
1908 boolean gatherThis = false;
1909 for (int a = 0; a < af.alignPanels.size(); a++)
1911 AlignmentPanel ap = af.alignPanels.get(a);
1912 if (viewId.equals(ap.av.getSequenceSetId()))
1915 ap.av.setGatherViewsHere(false);
1916 ap.av.setExplodedGeometry(af.getBounds());
1917 source.addAlignmentPanel(ap, false);
1923 af.alignPanels.clear();
1924 af.closeMenuItem_actionPerformed(true);
1931 jalview.gui.VamsasApplication v_client = null;
1934 public void vamsasImport_actionPerformed(ActionEvent e)
1936 if (v_client == null)
1938 // Load and try to start a session.
1939 JalviewFileChooser chooser = new JalviewFileChooser(
1940 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1942 chooser.setFileView(new JalviewFileView());
1943 chooser.setDialogTitle(MessageManager
1944 .getString("label.open_saved_vamsas_session"));
1945 chooser.setToolTipText(MessageManager
1946 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1948 int value = chooser.showOpenDialog(this);
1950 if (value == JalviewFileChooser.APPROVE_OPTION)
1952 String fle = chooser.getSelectedFile().toString();
1953 if (!vamsasImport(chooser.getSelectedFile()))
1956 .showInternalMessageDialog(
1958 MessageManager.formatMessage(
1959 "label.couldnt_import_as_vamsas_session",
1960 new Object[] { fle }),
1962 .getString("label.vamsas_document_import_failed"),
1963 JvOptionPane.ERROR_MESSAGE);
1969 jalview.bin.Cache.log
1970 .error("Implementation error - load session from a running session is not supported.");
1975 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1978 * @return true if import was a success and a session was started.
1980 public boolean vamsasImport(URL url)
1982 // TODO: create progress bar
1983 if (v_client != null)
1986 jalview.bin.Cache.log
1987 .error("Implementation error - load session from a running session is not supported.");
1993 // copy the URL content to a temporary local file
1994 // TODO: be a bit cleverer here with nio (?!)
1995 File file = File.createTempFile("vdocfromurl", ".vdj");
1996 FileOutputStream fos = new FileOutputStream(file);
1997 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1998 byte[] buffer = new byte[2048];
2000 while ((ln = bis.read(buffer)) > -1)
2002 fos.write(buffer, 0, ln);
2006 v_client = new jalview.gui.VamsasApplication(this, file,
2007 url.toExternalForm());
2008 } catch (Exception ex)
2010 jalview.bin.Cache.log.error(
2011 "Failed to create new vamsas session from contents of URL "
2015 setupVamsasConnectedGui();
2016 v_client.initial_update(); // TODO: thread ?
2017 return v_client.inSession();
2021 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2024 * @return true if import was a success and a session was started.
2026 public boolean vamsasImport(File file)
2028 if (v_client != null)
2031 jalview.bin.Cache.log
2032 .error("Implementation error - load session from a running session is not supported.");
2036 setProgressBar(MessageManager.formatMessage(
2037 "status.importing_vamsas_session_from",
2038 new Object[] { file.getName() }), file.hashCode());
2041 v_client = new jalview.gui.VamsasApplication(this, file, null);
2042 } catch (Exception ex)
2044 setProgressBar(MessageManager.formatMessage(
2045 "status.importing_vamsas_session_from",
2046 new Object[] { file.getName() }), file.hashCode());
2047 jalview.bin.Cache.log.error(
2048 "New vamsas session from existing session file failed:", ex);
2051 setupVamsasConnectedGui();
2052 v_client.initial_update(); // TODO: thread ?
2053 setProgressBar(MessageManager.formatMessage(
2054 "status.importing_vamsas_session_from",
2055 new Object[] { file.getName() }), file.hashCode());
2056 return v_client.inSession();
2059 public boolean joinVamsasSession(String mysesid)
2061 if (v_client != null)
2065 .getString("error.try_join_vamsas_session_another"));
2067 if (mysesid == null)
2070 MessageManager.getString("error.invalid_vamsas_session_id"));
2072 v_client = new VamsasApplication(this, mysesid);
2073 setupVamsasConnectedGui();
2074 v_client.initial_update();
2075 return (v_client.inSession());
2079 public void vamsasStart_actionPerformed(ActionEvent e)
2081 if (v_client == null)
2084 // we just start a default session for moment.
2086 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2087 * getProperty("LAST_DIRECTORY"));
2089 * chooser.setFileView(new JalviewFileView());
2090 * chooser.setDialogTitle("Load Vamsas file");
2091 * chooser.setToolTipText("Import");
2093 * int value = chooser.showOpenDialog(this);
2095 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2096 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2098 v_client = new VamsasApplication(this);
2099 setupVamsasConnectedGui();
2100 v_client.initial_update(); // TODO: thread ?
2104 // store current data in session.
2105 v_client.push_update(); // TODO: thread
2109 protected void setupVamsasConnectedGui()
2111 vamsasStart.setText(MessageManager.getString("label.session_update"));
2112 vamsasSave.setVisible(true);
2113 vamsasStop.setVisible(true);
2114 vamsasImport.setVisible(false); // Document import to existing session is
2115 // not possible for vamsas-client-1.0.
2118 protected void setupVamsasDisconnectedGui()
2120 vamsasSave.setVisible(false);
2121 vamsasStop.setVisible(false);
2122 vamsasImport.setVisible(true);
2123 vamsasStart.setText(MessageManager
2124 .getString("label.new_vamsas_session"));
2128 public void vamsasStop_actionPerformed(ActionEvent e)
2130 if (v_client != null)
2132 v_client.end_session();
2134 setupVamsasDisconnectedGui();
2138 protected void buildVamsasStMenu()
2140 if (v_client == null)
2142 String[] sess = null;
2145 sess = VamsasApplication.getSessionList();
2146 } catch (Exception e)
2148 jalview.bin.Cache.log.warn(
2149 "Problem getting current sessions list.", e);
2154 jalview.bin.Cache.log.debug("Got current sessions list: "
2155 + sess.length + " entries.");
2156 VamsasStMenu.removeAll();
2157 for (int i = 0; i < sess.length; i++)
2159 JMenuItem sessit = new JMenuItem();
2160 sessit.setText(sess[i]);
2161 sessit.setToolTipText(MessageManager.formatMessage(
2162 "label.connect_to_session", new Object[] { sess[i] }));
2163 final Desktop dsktp = this;
2164 final String mysesid = sess[i];
2165 sessit.addActionListener(new ActionListener()
2169 public void actionPerformed(ActionEvent e)
2171 if (dsktp.v_client == null)
2173 Thread rthr = new Thread(new Runnable()
2179 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2180 dsktp.setupVamsasConnectedGui();
2181 dsktp.v_client.initial_update();
2189 VamsasStMenu.add(sessit);
2191 // don't show an empty menu.
2192 VamsasStMenu.setVisible(sess.length > 0);
2197 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2198 VamsasStMenu.removeAll();
2199 VamsasStMenu.setVisible(false);
2204 // Not interested in the content. Just hide ourselves.
2205 VamsasStMenu.setVisible(false);
2210 public void vamsasSave_actionPerformed(ActionEvent e)
2212 if (v_client != null)
2214 JalviewFileChooser chooser = new JalviewFileChooser(
2215 Cache.getProperty("LAST_DIRECTORY"), "vdj",// TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2218 chooser.setFileView(new JalviewFileView());
2219 chooser.setDialogTitle(MessageManager
2220 .getString("label.save_vamsas_document_archive"));
2222 int value = chooser.showSaveDialog(this);
2224 if (value == JalviewFileChooser.APPROVE_OPTION)
2226 java.io.File choice = chooser.getSelectedFile();
2227 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2228 "label.saving_vamsas_doc",
2229 new Object[] { choice.getName() }));
2230 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2231 String warnmsg = null;
2232 String warnttl = null;
2235 v_client.vclient.storeDocument(choice);
2238 warnttl = "Serious Problem saving Vamsas Document";
2239 warnmsg = ex.toString();
2240 jalview.bin.Cache.log.error("Error Whilst saving document to "
2243 } catch (Exception ex)
2245 warnttl = "Problem saving Vamsas Document.";
2246 warnmsg = ex.toString();
2247 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2251 removeProgressPanel(progpanel);
2252 if (warnmsg != null)
2254 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2256 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2262 JPanel vamUpdate = null;
2265 * hide vamsas user gui bits when a vamsas document event is being handled.
2268 * true to hide gui, false to reveal gui
2270 public void setVamsasUpdate(boolean b)
2272 Cache.log.debug("Setting gui for Vamsas update "
2273 + (b ? "in progress" : "finished"));
2275 if (vamUpdate != null)
2277 this.removeProgressPanel(vamUpdate);
2281 vamUpdate = this.addProgressPanel(MessageManager
2282 .getString("label.updating_vamsas_session"));
2284 vamsasStart.setVisible(!b);
2285 vamsasStop.setVisible(!b);
2286 vamsasSave.setVisible(!b);
2289 public JInternalFrame[] getAllFrames()
2291 return desktop.getAllFrames();
2295 * Checks the given url to see if it gives a response indicating that the user
2296 * should be informed of a new questionnaire.
2300 public void checkForQuestionnaire(String url)
2302 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2303 // javax.swing.SwingUtilities.invokeLater(jvq);
2304 new Thread(jvq).start();
2307 public void checkURLLinks()
2309 // Thread off the URL link checker
2310 addDialogThread(new Runnable()
2315 if (Cache.getDefault("CHECKURLLINKS", true))
2317 // check what the actual links are - if it's just the default don't
2318 // bother with the warning
2319 List<String> links = Preferences.sequenceUrlLinks
2322 // only need to check links if there is one with a
2323 // SEQUENCE_ID which is not the default EMBL_EBI link
2324 ListIterator<String> li = links.listIterator();
2325 boolean check = false;
2326 List<JLabel> urls = new ArrayList<JLabel>();
2327 while (li.hasNext())
2329 String link = li.next();
2330 if (link.contains(SEQUENCE_ID)
2331 && !link.equals(UrlConstants.DEFAULT_STRING))
2334 int barPos = link.indexOf("|");
2335 String urlMsg = barPos == -1 ? link : link.substring(0,
2336 barPos) + ": " + link.substring(barPos + 1);
2337 urls.add(new JLabel(urlMsg));
2345 // ask user to check in case URL links use old style tokens
2346 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2347 JPanel msgPanel = new JPanel();
2348 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2349 msgPanel.add(Box.createVerticalGlue());
2350 JLabel msg = new JLabel(
2352 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2353 JLabel msg2 = new JLabel(
2355 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2357 for (JLabel url : urls)
2363 final JCheckBox jcb = new JCheckBox(
2364 MessageManager.getString("label.do_not_display_again"));
2365 jcb.addActionListener(new ActionListener()
2368 public void actionPerformed(ActionEvent e)
2370 // update Cache settings for "don't show this again"
2371 boolean showWarningAgain = !jcb.isSelected();
2372 Cache.setProperty("CHECKURLLINKS",
2373 Boolean.valueOf(showWarningAgain).toString());
2378 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2380 .getString("label.SEQUENCE_ID_no_longer_used"),
2381 JvOptionPane.WARNING_MESSAGE);
2388 * Proxy class for JDesktopPane which optionally displays the current memory
2389 * usage and highlights the desktop area with a red bar if free memory runs
2394 public class MyDesktopPane extends JDesktopPane implements Runnable
2397 private static final float ONE_MB = 1048576f;
2399 boolean showMemoryUsage = false;
2403 java.text.NumberFormat df;
2405 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2408 public MyDesktopPane(boolean showMemoryUsage)
2410 showMemoryUsage(showMemoryUsage);
2413 public void showMemoryUsage(boolean showMemory)
2415 this.showMemoryUsage = showMemory;
2418 Thread worker = new Thread(this);
2423 public boolean isShowMemoryUsage()
2425 return showMemoryUsage;
2431 df = java.text.NumberFormat.getNumberInstance();
2432 df.setMaximumFractionDigits(2);
2433 runtime = Runtime.getRuntime();
2435 while (showMemoryUsage)
2439 maxMemory = runtime.maxMemory() / ONE_MB;
2440 allocatedMemory = runtime.totalMemory() / ONE_MB;
2441 freeMemory = runtime.freeMemory() / ONE_MB;
2442 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2444 percentUsage = (totalFreeMemory / maxMemory) * 100;
2446 // if (percentUsage < 20)
2448 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2450 // instance.set.setBorder(border1);
2453 // sleep after showing usage
2455 } catch (Exception ex)
2457 ex.printStackTrace();
2463 public void paintComponent(Graphics g)
2465 if (showMemoryUsage && g != null && df != null)
2467 if (percentUsage < 20)
2469 g.setColor(Color.red);
2471 FontMetrics fm = g.getFontMetrics();
2474 g.drawString(MessageManager.formatMessage(
2475 "label.memory_stats",
2476 new Object[] { df.format(totalFreeMemory),
2477 df.format(maxMemory), df.format(percentUsage) }), 10,
2478 getHeight() - fm.getHeight());
2485 * fixes stacking order after a modal dialog to ensure windows that should be
2486 * on top actually are
2488 public void relayerWindows()
2493 protected JMenuItem groovyShell;
2496 * Accessor method to quickly get all the AlignmentFrames loaded.
2498 * @return an array of AlignFrame, or null if none found
2500 public static AlignFrame[] getAlignFrames()
2502 if (Jalview.isHeadlessMode())
2504 // Desktop.desktop is null in headless mode
2505 return new AlignFrame[] { Jalview.currentAlignFrame };
2508 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2514 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2516 for (int i = frames.length - 1; i > -1; i--)
2518 if (frames[i] instanceof AlignFrame)
2520 avp.add((AlignFrame) frames[i]);
2522 else if (frames[i] instanceof SplitFrame)
2525 * Also check for a split frame containing an AlignFrame
2527 GSplitFrame sf = (GSplitFrame) frames[i];
2528 if (sf.getTopFrame() instanceof AlignFrame)
2530 avp.add((AlignFrame) sf.getTopFrame());
2532 if (sf.getBottomFrame() instanceof AlignFrame)
2534 avp.add((AlignFrame) sf.getBottomFrame());
2538 if (avp.size() == 0)
2542 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2547 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2551 public GStructureViewer[] getJmols()
2553 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2559 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2561 for (int i = frames.length - 1; i > -1; i--)
2563 if (frames[i] instanceof AppJmol)
2565 GStructureViewer af = (GStructureViewer) frames[i];
2569 if (avp.size() == 0)
2573 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2578 * Add Groovy Support to Jalview
2580 public void groovyShell_actionPerformed()
2584 openGroovyConsole();
2585 } catch (Exception ex)
2587 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2588 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2590 MessageManager.getString("label.couldnt_create_groovy_shell"),
2591 MessageManager.getString("label.groovy_support_failed"),
2592 JvOptionPane.ERROR_MESSAGE);
2597 * Open the Groovy console
2599 void openGroovyConsole()
2601 if (groovyConsole == null)
2603 groovyConsole = new groovy.ui.Console();
2604 groovyConsole.setVariable("Jalview", this);
2605 groovyConsole.run();
2608 * We allow only one console at a time, so that AlignFrame menu option
2609 * 'Calculate | Run Groovy script' is unambiguous.
2610 * Disable 'Groovy Console', and enable 'Run script', when the console is
2611 * opened, and the reverse when it is closed
2613 Window window = (Window) groovyConsole.getFrame();
2614 window.addWindowListener(new WindowAdapter()
2617 public void windowClosed(WindowEvent e)
2620 * rebind CMD-Q from Groovy Console to Jalview Quit
2623 enableExecuteGroovy(false);
2629 * show Groovy console window (after close and reopen)
2631 ((Window) groovyConsole.getFrame()).setVisible(true);
2634 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2635 * and disable opening a second console
2637 enableExecuteGroovy(true);
2641 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2642 * binding when opened
2644 protected void addQuitHandler()
2646 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2647 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2648 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2649 getRootPane().getActionMap().put("Quit", new AbstractAction()
2652 public void actionPerformed(ActionEvent e)
2660 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2663 * true if Groovy console is open
2665 public void enableExecuteGroovy(boolean enabled)
2668 * disable opening a second Groovy console
2669 * (or re-enable when the console is closed)
2671 groovyShell.setEnabled(!enabled);
2673 AlignFrame[] alignFrames = getAlignFrames();
2674 if (alignFrames != null)
2676 for (AlignFrame af : alignFrames)
2678 af.setGroovyEnabled(enabled);
2684 * Progress bars managed by the IProgressIndicator method.
2686 private Hashtable<Long, JPanel> progressBars;
2688 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2693 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2696 public void setProgressBar(String message, long id)
2698 if (progressBars == null)
2700 progressBars = new Hashtable<Long, JPanel>();
2701 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2704 if (progressBars.get(new Long(id)) != null)
2706 JPanel panel = progressBars.remove(new Long(id));
2707 if (progressBarHandlers.contains(new Long(id)))
2709 progressBarHandlers.remove(new Long(id));
2711 removeProgressPanel(panel);
2715 progressBars.put(new Long(id), addProgressPanel(message));
2722 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2723 * jalview.gui.IProgressIndicatorHandler)
2726 public void registerHandler(final long id,
2727 final IProgressIndicatorHandler handler)
2729 if (progressBarHandlers == null
2730 || !progressBars.containsKey(new Long(id)))
2734 .getString("error.call_setprogressbar_before_registering_handler"));
2736 progressBarHandlers.put(new Long(id), handler);
2737 final JPanel progressPanel = progressBars.get(new Long(id));
2738 if (handler.canCancel())
2740 JButton cancel = new JButton(
2741 MessageManager.getString("action.cancel"));
2742 final IProgressIndicator us = this;
2743 cancel.addActionListener(new ActionListener()
2747 public void actionPerformed(ActionEvent e)
2749 handler.cancelActivity(id);
2750 us.setProgressBar(MessageManager.formatMessage(
2751 "label.cancelled_params",
2752 new Object[] { ((JLabel) progressPanel.getComponent(0))
2756 progressPanel.add(cancel, BorderLayout.EAST);
2762 * @return true if any progress bars are still active
2765 public boolean operationInProgress()
2767 if (progressBars != null && progressBars.size() > 0)
2775 * This will return the first AlignFrame holding the given viewport instance.
2776 * It will break if there are more than one AlignFrames viewing a particular
2780 * @return alignFrame for viewport
2782 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2784 if (desktop != null)
2786 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2787 for (int panel = 0; aps != null && panel < aps.length; panel++)
2789 if (aps[panel] != null && aps[panel].av == viewport)
2791 return aps[panel].alignFrame;
2798 public VamsasApplication getVamsasApplication()
2805 * flag set if jalview GUI is being operated programmatically
2807 private boolean inBatchMode = false;
2810 * check if jalview GUI is being operated programmatically
2812 * @return inBatchMode
2814 public boolean isInBatchMode()
2820 * set flag if jalview GUI is being operated programmatically
2822 * @param inBatchMode
2824 public void setInBatchMode(boolean inBatchMode)
2826 this.inBatchMode = inBatchMode;
2829 public void startServiceDiscovery()
2831 startServiceDiscovery(false);
2834 public void startServiceDiscovery(boolean blocking)
2836 boolean alive = true;
2837 Thread t0 = null, t1 = null, t2 = null;
2838 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2841 // todo: changesupport handlers need to be transferred
2842 if (discoverer == null)
2844 discoverer = new jalview.ws.jws1.Discoverer();
2845 // register PCS handler for desktop.
2846 discoverer.addPropertyChangeListener(changeSupport);
2848 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2849 // until we phase out completely
2850 (t0 = new Thread(discoverer)).start();
2853 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2855 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2857 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2859 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2865 // TODO: do rest service discovery
2874 } catch (Exception e)
2877 alive = (t1 != null && t1.isAlive())
2878 || (t2 != null && t2.isAlive())
2879 || (t3 != null && t3.isAlive())
2880 || (t0 != null && t0.isAlive());
2886 * called to check if the service discovery process completed successfully.
2890 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2892 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2894 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2895 .getErrorMessages();
2898 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2900 if (serviceChangedDialog == null)
2902 // only run if we aren't already displaying one of these.
2903 addDialogThread(serviceChangedDialog = new Runnable()
2910 * JalviewDialog jd =new JalviewDialog() {
2912 * @Override protected void cancelPressed() { // TODO
2913 * Auto-generated method stub
2915 * }@Override protected void okPressed() { // TODO
2916 * Auto-generated method stub
2918 * }@Override protected void raiseClosed() { // TODO
2919 * Auto-generated method stub
2921 * } }; jd.initDialogFrame(new
2922 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2923 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2924 * + " or mis-configured HTTP proxy settings.<br/>" +
2925 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2927 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2928 * ), true, true, "Web Service Configuration Problem", 450,
2931 * jd.waitForInput();
2937 "<html><table width=\"450\"><tr><td>"
2939 + "</td></tr></table>"
2940 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2941 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2942 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2943 + " Tools->Preferences dialog box to change them.</p></html>"),
2944 "Web Service Configuration Problem",
2945 JvOptionPane.DEFAULT_OPTION,
2946 JvOptionPane.ERROR_MESSAGE);
2947 serviceChangedDialog = null;
2956 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2963 private Runnable serviceChangedDialog = null;
2966 * start a thread to open a URL in the configured browser. Pops up a warning
2967 * dialog to the user if there is an exception when calling out to the browser
2972 public static void showUrl(final String url)
2974 showUrl(url, Desktop.instance);
2978 * Like showUrl but allows progress handler to be specified
2982 * (null) or object implementing IProgressIndicator
2984 public static void showUrl(final String url,
2985 final IProgressIndicator progress)
2987 new Thread(new Runnable()
2994 if (progress != null)
2996 progress.setProgressBar(MessageManager.formatMessage(
2997 "status.opening_params", new Object[] { url }), this
3000 jalview.util.BrowserLauncher.openURL(url);
3001 } catch (Exception ex)
3003 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3005 .getString("label.web_browser_not_found_unix"),
3006 MessageManager.getString("label.web_browser_not_found"),
3007 JvOptionPane.WARNING_MESSAGE);
3009 ex.printStackTrace();
3011 if (progress != null)
3013 progress.setProgressBar(null, this.hashCode());
3019 public static WsParamSetManager wsparamManager = null;
3021 public static ParamManager getUserParameterStore()
3023 if (wsparamManager == null)
3025 wsparamManager = new WsParamSetManager();
3027 return wsparamManager;
3031 * static hyperlink handler proxy method for use by Jalview's internal windows
3035 public static void hyperlinkUpdate(HyperlinkEvent e)
3037 if (e.getEventType() == EventType.ACTIVATED)
3042 url = e.getURL().toString();
3043 Desktop.showUrl(url);
3044 } catch (Exception x)
3048 if (Cache.log != null)
3050 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3054 System.err.println("Couldn't handle string " + url
3058 // ignore any exceptions due to dud links.
3065 * single thread that handles display of dialogs to user.
3067 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3070 * flag indicating if dialogExecutor should try to acquire a permit
3072 private volatile boolean dialogPause = true;
3077 private java.util.concurrent.Semaphore block = new Semaphore(0);
3079 private static groovy.ui.Console groovyConsole;
3082 * add another dialog thread to the queue
3086 public void addDialogThread(final Runnable prompter)
3088 dialogExecutor.submit(new Runnable()
3098 } catch (InterruptedException x)
3103 if (instance == null)
3109 SwingUtilities.invokeAndWait(prompter);
3110 } catch (Exception q)
3112 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3118 public void startDialogQueue()
3120 // set the flag so we don't pause waiting for another permit and semaphore
3121 // the current task to begin
3122 dialogPause = false;
3127 protected void snapShotWindow_actionPerformed(ActionEvent e)
3131 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3132 "View of Desktop", getWidth(), getHeight(), of = new File(
3133 "Jalview_snapshot" + System.currentTimeMillis()
3134 + ".eps"), "View of desktop", null, 0, false);
3137 paintAll(im.getGraphics());
3139 } catch (Exception q)
3141 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3145 Cache.log.info("Successfully written snapshot to file "
3146 + of.getAbsolutePath());
3150 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3151 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3152 * and location last time the view was expanded (if any). However it does not
3153 * remember the split pane divider location - this is set to match the
3154 * 'exploding' frame.
3158 public void explodeViews(SplitFrame sf)
3160 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3161 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3162 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3164 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3166 int viewCount = topPanels.size();
3173 * Processing in reverse order works, forwards order leaves the first panels
3174 * not visible. I don't know why!
3176 for (int i = viewCount - 1; i >= 0; i--)
3179 * Make new top and bottom frames. These take over the respective
3180 * AlignmentPanel objects, including their AlignmentViewports, so the
3181 * cdna/protein relationships between the viewports is carried over to the
3184 * explodedGeometry holds the (x, y) position of the previously exploded
3185 * SplitFrame, and the (width, height) of the AlignFrame component
3187 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3188 AlignFrame newTopFrame = new AlignFrame(topPanel);
3189 newTopFrame.setSize(oldTopFrame.getSize());
3190 newTopFrame.setVisible(true);
3191 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3192 .getExplodedGeometry();
3193 if (geometry != null)
3195 newTopFrame.setSize(geometry.getSize());
3198 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3199 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3200 newBottomFrame.setSize(oldBottomFrame.getSize());
3201 newBottomFrame.setVisible(true);
3202 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3203 .getExplodedGeometry();
3204 if (geometry != null)
3206 newBottomFrame.setSize(geometry.getSize());
3209 topPanel.av.setGatherViewsHere(false);
3210 bottomPanel.av.setGatherViewsHere(false);
3211 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3213 if (geometry != null)
3215 splitFrame.setLocation(geometry.getLocation());
3217 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3221 * Clear references to the panels (now relocated in the new SplitFrames)
3222 * before closing the old SplitFrame.
3225 bottomPanels.clear();
3230 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3231 * back into the given SplitFrame as additional views. Note that the gathered
3232 * frames may themselves have multiple views.
3236 public void gatherViews(GSplitFrame source)
3239 * special handling of explodedGeometry for a view within a SplitFrame: - it
3240 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3241 * height) of the AlignFrame component
3243 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3244 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3245 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3246 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3247 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3248 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3250 myTopFrame.viewport.setGatherViewsHere(true);
3251 myBottomFrame.viewport.setGatherViewsHere(true);
3252 String topViewId = myTopFrame.viewport.getSequenceSetId();
3253 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3255 JInternalFrame[] frames = desktop.getAllFrames();
3256 for (JInternalFrame frame : frames)
3258 if (frame instanceof SplitFrame && frame != source)
3260 SplitFrame sf = (SplitFrame) frame;
3261 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3262 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3263 boolean gatherThis = false;
3264 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3266 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3267 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3268 if (topViewId.equals(topPanel.av.getSequenceSetId())
3269 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3272 topPanel.av.setGatherViewsHere(false);
3273 bottomPanel.av.setGatherViewsHere(false);
3274 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3275 topFrame.getSize()));
3276 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3277 .getLocation(), bottomFrame.getSize()));
3278 myTopFrame.addAlignmentPanel(topPanel, false);
3279 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3285 topFrame.getAlignPanels().clear();
3286 bottomFrame.getAlignPanels().clear();
3293 * The dust settles...give focus to the tab we did this from.
3295 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3298 public static groovy.ui.Console getGroovyConsole()
3300 return groovyConsole;
3303 public static void transferFromDropTarget(List<String> files,
3304 List<DataSourceType> protocols, DropTargetDropEvent evt,
3309 DataFlavor uriListFlavor = new DataFlavor(
3310 "text/uri-list;class=java.lang.String");
3311 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3313 // Works on Windows and MacOSX
3314 Cache.log.debug("Drop handled as javaFileListFlavor");
3315 for (Object file : (List) t
3316 .getTransferData(DataFlavor.javaFileListFlavor))
3318 files.add(((File) file).toString());
3319 protocols.add(DataSourceType.FILE);
3324 // Unix like behaviour
3325 boolean added = false;
3327 if (t.isDataFlavorSupported(uriListFlavor))
3329 Cache.log.debug("Drop handled as uriListFlavor");
3330 // This is used by Unix drag system
3331 data = (String) t.getTransferData(uriListFlavor);
3335 // fallback to text: workaround - on OSX where there's a JVM bug
3336 Cache.log.debug("standard URIListFlavor failed. Trying text");
3337 // try text fallback
3338 data = (String) t.getTransferData(new DataFlavor(
3339 "text/plain;class=java.lang.String"));
3340 if (Cache.log.isDebugEnabled())
3342 Cache.log.debug("fallback returned " + data);
3345 while (protocols.size() < files.size())
3347 Cache.log.debug("Adding missing FILE protocol for "
3348 + files.get(protocols.size()));
3349 protocols.add(DataSourceType.FILE);
3351 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3352 data, "\r\n"); st.hasMoreTokens();)
3355 String s = st.nextToken();
3356 if (s.startsWith("#"))
3358 // the line is a comment (as per the RFC 2483)
3361 java.net.URI uri = new java.net.URI(s);
3362 if (uri.getScheme().toLowerCase().startsWith("http"))
3364 protocols.add(DataSourceType.URL);
3365 files.add(uri.toString());
3369 // otherwise preserve old behaviour: catch all for file objects
3370 java.io.File file = new java.io.File(uri);
3371 protocols.add(DataSourceType.FILE);
3372 files.add(file.toString());
3375 if (Cache.log.isDebugEnabled())
3377 if (data == null || !added)
3380 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3381 for (DataFlavor fl : t.getTransferDataFlavors())
3383 Cache.log.debug("Supported transfer dataflavor: "
3385 Object df = t.getTransferData(fl);
3388 Cache.log.debug("Retrieves: " + df);
3392 Cache.log.debug("Retrieved nothing");