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.EMBLEBI_STRING;
24 import static jalview.util.UrlConstants.SEQUENCE_ID;
26 import jalview.api.AlignViewportI;
27 import jalview.api.AlignmentViewPanel;
28 import jalview.bin.Cache;
29 import jalview.bin.Jalview;
30 import jalview.io.DataSourceType;
31 import jalview.io.FileFormat;
32 import jalview.io.FileFormatException;
33 import jalview.io.FileFormatI;
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.util.ImageMaker;
42 import jalview.util.MessageManager;
43 import jalview.util.Platform;
44 import jalview.viewmodel.AlignmentViewport;
45 import jalview.ws.params.ParamManager;
47 import java.awt.BorderLayout;
48 import java.awt.Color;
49 import java.awt.Dimension;
50 import java.awt.FontMetrics;
51 import java.awt.Graphics;
52 import java.awt.GridLayout;
53 import java.awt.Point;
54 import java.awt.Rectangle;
55 import java.awt.Toolkit;
56 import java.awt.Window;
57 import java.awt.datatransfer.Clipboard;
58 import java.awt.datatransfer.ClipboardOwner;
59 import java.awt.datatransfer.DataFlavor;
60 import java.awt.datatransfer.Transferable;
61 import java.awt.dnd.DnDConstants;
62 import java.awt.dnd.DropTargetDragEvent;
63 import java.awt.dnd.DropTargetDropEvent;
64 import java.awt.dnd.DropTargetEvent;
65 import java.awt.dnd.DropTargetListener;
66 import java.awt.event.ActionEvent;
67 import java.awt.event.ActionListener;
68 import java.awt.event.FocusEvent;
69 import java.awt.event.FocusListener;
70 import java.awt.event.KeyEvent;
71 import java.awt.event.MouseAdapter;
72 import java.awt.event.MouseEvent;
73 import java.awt.event.WindowAdapter;
74 import java.awt.event.WindowEvent;
75 import java.beans.PropertyChangeEvent;
76 import java.beans.PropertyChangeListener;
77 import java.io.BufferedInputStream;
79 import java.io.FileOutputStream;
81 import java.util.ArrayList;
82 import java.util.Hashtable;
83 import java.util.List;
84 import java.util.ListIterator;
85 import java.util.StringTokenizer;
86 import java.util.Vector;
87 import java.util.concurrent.ExecutorService;
88 import java.util.concurrent.Executors;
89 import java.util.concurrent.Semaphore;
91 import javax.swing.AbstractAction;
92 import javax.swing.Box;
93 import javax.swing.BoxLayout;
94 import javax.swing.DefaultDesktopManager;
95 import javax.swing.DesktopManager;
96 import javax.swing.JButton;
97 import javax.swing.JCheckBox;
98 import javax.swing.JComboBox;
99 import javax.swing.JComponent;
100 import javax.swing.JDesktopPane;
101 import javax.swing.JFrame;
102 import javax.swing.JInternalFrame;
103 import javax.swing.JLabel;
104 import javax.swing.JMenuItem;
105 import javax.swing.JOptionPane;
106 import javax.swing.JPanel;
107 import javax.swing.JPopupMenu;
108 import javax.swing.JProgressBar;
109 import javax.swing.KeyStroke;
110 import javax.swing.SwingUtilities;
111 import javax.swing.event.HyperlinkEvent;
112 import javax.swing.event.HyperlinkEvent.EventType;
113 import javax.swing.event.InternalFrameAdapter;
114 import javax.swing.event.InternalFrameEvent;
115 import javax.swing.event.MenuEvent;
116 import javax.swing.event.MenuListener;
123 * @version $Revision: 1.155 $
125 public class Desktop extends jalview.jbgui.GDesktop implements
126 DropTargetListener, ClipboardOwner, IProgressIndicator,
127 jalview.api.StructureSelectionManagerProvider
130 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
133 * news reader - null if it was never started.
135 private BlogReader jvnews = null;
137 private File projectFile;
141 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
143 public void addJalviewPropertyChangeListener(
144 PropertyChangeListener listener)
146 changeSupport.addJalviewPropertyChangeListener(listener);
150 * @param propertyName
152 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
153 * java.beans.PropertyChangeListener)
155 public void addJalviewPropertyChangeListener(String propertyName,
156 PropertyChangeListener listener)
158 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
162 * @param propertyName
164 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
165 * java.beans.PropertyChangeListener)
167 public void removeJalviewPropertyChangeListener(String propertyName,
168 PropertyChangeListener listener)
170 changeSupport.removeJalviewPropertyChangeListener(propertyName,
174 /** Singleton Desktop instance */
175 public static Desktop instance;
177 public static MyDesktopPane desktop;
179 static int openFrameCount = 0;
181 static final int xOffset = 30;
183 static final int yOffset = 30;
185 public static jalview.ws.jws1.Discoverer discoverer;
187 public static Object[] jalviewClipboard;
189 public static boolean internalCopy = false;
191 static int fileLoadingCount = 0;
193 class MyDesktopManager implements DesktopManager
196 private DesktopManager delegate;
198 public MyDesktopManager(DesktopManager delegate)
200 this.delegate = delegate;
204 public void activateFrame(JInternalFrame f)
208 delegate.activateFrame(f);
209 } catch (NullPointerException npe)
211 Point p = getMousePosition();
212 instance.showPasteMenu(p.x, p.y);
217 public void beginDraggingFrame(JComponent f)
219 delegate.beginDraggingFrame(f);
223 public void beginResizingFrame(JComponent f, int direction)
225 delegate.beginResizingFrame(f, direction);
229 public void closeFrame(JInternalFrame f)
231 delegate.closeFrame(f);
235 public void deactivateFrame(JInternalFrame f)
237 delegate.deactivateFrame(f);
241 public void deiconifyFrame(JInternalFrame f)
243 delegate.deiconifyFrame(f);
247 public void dragFrame(JComponent f, int newX, int newY)
253 delegate.dragFrame(f, newX, newY);
257 public void endDraggingFrame(JComponent f)
259 delegate.endDraggingFrame(f);
263 public void endResizingFrame(JComponent f)
265 delegate.endResizingFrame(f);
269 public void iconifyFrame(JInternalFrame f)
271 delegate.iconifyFrame(f);
275 public void maximizeFrame(JInternalFrame f)
277 delegate.maximizeFrame(f);
281 public void minimizeFrame(JInternalFrame f)
283 delegate.minimizeFrame(f);
287 public void openFrame(JInternalFrame f)
289 delegate.openFrame(f);
293 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
300 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
304 public void setBoundsForFrame(JComponent f, int newX, int newY,
305 int newWidth, int newHeight)
307 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
310 // All other methods, simply delegate
315 * Creates a new Desktop object.
320 * A note to implementors. It is ESSENTIAL that any activities that might
321 * block are spawned off as threads rather than waited for during this
325 doVamsasClientCheck();
327 groovyShell = new JMenuItem();
328 groovyShell.setText(MessageManager.getString("label.groovy_console"));
329 groovyShell.addActionListener(new ActionListener()
332 public void actionPerformed(ActionEvent e)
334 groovyShell_actionPerformed();
337 toolsMenu.add(groovyShell);
338 groovyShell.setVisible(true);
340 doConfigureStructurePrefs();
341 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
342 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
345 boolean showjconsole = jalview.bin.Cache.getDefault(
346 "SHOW_JAVA_CONSOLE", false);
347 desktop = new MyDesktopPane(selmemusage);
348 if (Platform.isAMac())
350 desktop.setDoubleBuffered(false);
352 showMemusage.setSelected(selmemusage);
353 desktop.setBackground(Color.white);
354 getContentPane().setLayout(new BorderLayout());
355 // alternate config - have scrollbars - see notes in JAL-153
356 // JScrollPane sp = new JScrollPane();
357 // sp.getViewport().setView(desktop);
358 // getContentPane().add(sp, BorderLayout.CENTER);
359 getContentPane().add(desktop, BorderLayout.CENTER);
360 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
362 // This line prevents Windows Look&Feel resizing all new windows to maximum
363 // if previous window was maximised
364 desktop.setDesktopManager(new MyDesktopManager(
365 new DefaultDesktopManager()));
367 Rectangle dims = getLastKnownDimensions("");
374 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
375 setBounds((screenSize.width - 900) / 2,
376 (screenSize.height - 650) / 2, 900, 650);
378 jconsole = new Console(this, showjconsole);
379 // add essential build information
380 jconsole.setHeader("Jalview Version: "
381 + jalview.bin.Cache.getProperty("VERSION") + "\n"
382 + "Jalview Installation: "
383 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
384 + "\n" + "Build Date: "
385 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
386 + "Java version: " + System.getProperty("java.version") + "\n"
387 + System.getProperty("os.arch") + " "
388 + System.getProperty("os.name") + " "
389 + System.getProperty("os.version"));
391 showConsole(showjconsole);
393 showNews.setVisible(false);
397 this.addWindowListener(new WindowAdapter()
400 public void windowClosing(WindowEvent evt)
407 this.addMouseListener(ma = new MouseAdapter()
410 public void mousePressed(MouseEvent evt)
412 if (evt.isPopupTrigger()) // Mac
414 showPasteMenu(evt.getX(), evt.getY());
419 public void mouseReleased(MouseEvent evt)
421 if (evt.isPopupTrigger()) // Windows
423 showPasteMenu(evt.getX(), evt.getY());
427 desktop.addMouseListener(ma);
429 this.addFocusListener(new FocusListener()
433 public void focusLost(FocusEvent e)
435 // TODO Auto-generated method stub
440 public void focusGained(FocusEvent e)
442 Cache.log.debug("Relaying windows after focus gain");
443 // make sure that we sort windows properly after we gain focus
444 instance.relayerWindows();
447 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
448 // Spawn a thread that shows the splashscreen
449 SwingUtilities.invokeLater(new Runnable()
459 // Thread off a new instance of the file chooser - this reduces the time it
460 // takes to open it later on.
461 new Thread(new Runnable()
466 Cache.log.debug("Filechooser init thread started.");
467 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
468 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
469 // jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
470 // jalview.io.AppletFormatAdapter.READABLE_FNAMES,
472 Cache.log.debug("Filechooser init thread finished.");
475 // Add the service change listener
476 changeSupport.addJalviewPropertyChangeListener("services",
477 new PropertyChangeListener()
481 public void propertyChange(PropertyChangeEvent evt)
483 Cache.log.debug("Firing service changed event for "
484 + evt.getNewValue());
485 JalviewServicesChanged(evt);
491 public void doConfigureStructurePrefs()
493 // configure services
494 StructureSelectionManager ssm = StructureSelectionManager
495 .getStructureSelectionManager(this);
496 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
498 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
499 Preferences.ADD_TEMPFACT_ANN, true));
500 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
501 Preferences.STRUCT_FROM_PDB, true));
502 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
503 Preferences.USE_RNAVIEW, true));
507 ssm.setAddTempFacAnnot(false);
508 ssm.setProcessSecondaryStructure(false);
509 ssm.setSecStructServices(false);
513 public void checkForNews()
515 final Desktop me = this;
516 // Thread off the news reader, in case there are connection problems.
517 addDialogThread(new Runnable()
522 Cache.log.debug("Starting news thread.");
524 jvnews = new BlogReader(me);
525 showNews.setVisible(true);
526 Cache.log.debug("Completed news thread.");
532 protected void showNews_actionPerformed(ActionEvent e)
534 showNews(showNews.isSelected());
537 void showNews(boolean visible)
540 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
541 showNews.setSelected(visible);
542 if (visible && !jvnews.isVisible())
544 new Thread(new Runnable()
549 long now = System.currentTimeMillis();
550 Desktop.instance.setProgressBar(
551 MessageManager.getString("status.refreshing_news"), now);
552 jvnews.refreshNews();
553 Desktop.instance.setProgressBar(null, now);
562 * recover the last known dimensions for a jalview window
565 * - empty string is desktop, all other windows have unique prefix
566 * @return null or last known dimensions scaled to current geometry (if last
567 * window geom was known)
569 Rectangle getLastKnownDimensions(String windowName)
571 // TODO: lock aspect ratio for scaling desktop Bug #0058199
572 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
573 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
574 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
575 String width = jalview.bin.Cache.getProperty(windowName
577 String height = jalview.bin.Cache.getProperty(windowName
579 if ((x != null) && (y != null) && (width != null) && (height != null))
581 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
582 .parseInt(width), ih = Integer.parseInt(height);
583 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
585 // attempt #1 - try to cope with change in screen geometry - this
586 // version doesn't preserve original jv aspect ratio.
587 // take ratio of current screen size vs original screen size.
588 double sw = ((1f * screenSize.width) / (1f * Integer
589 .parseInt(jalview.bin.Cache
590 .getProperty("SCREENGEOMETRY_WIDTH"))));
591 double sh = ((1f * screenSize.height) / (1f * Integer
592 .parseInt(jalview.bin.Cache
593 .getProperty("SCREENGEOMETRY_HEIGHT"))));
594 // rescale the bounds depending upon the current screen geometry.
595 ix = (int) (ix * sw);
596 iw = (int) (iw * sw);
597 iy = (int) (iy * sh);
598 ih = (int) (ih * sh);
599 while (ix >= screenSize.width)
601 jalview.bin.Cache.log
602 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
603 ix -= screenSize.width;
605 while (iy >= screenSize.height)
607 jalview.bin.Cache.log
608 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
609 iy -= screenSize.height;
611 jalview.bin.Cache.log.debug("Got last known dimensions for "
612 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
615 // return dimensions for new instance
616 return new Rectangle(ix, iy, iw, ih);
621 private void doVamsasClientCheck()
623 if (jalview.bin.Cache.vamsasJarsPresent())
625 setupVamsasDisconnectedGui();
626 VamsasMenu.setVisible(true);
627 final Desktop us = this;
628 VamsasMenu.addMenuListener(new MenuListener()
630 // this listener remembers when the menu was first selected, and
631 // doesn't rebuild the session list until it has been cleared and
633 boolean refresh = true;
636 public void menuCanceled(MenuEvent e)
642 public void menuDeselected(MenuEvent e)
648 public void menuSelected(MenuEvent e)
652 us.buildVamsasStMenu();
657 vamsasStart.setVisible(true);
661 void showPasteMenu(int x, int y)
663 JPopupMenu popup = new JPopupMenu();
664 JMenuItem item = new JMenuItem(
665 MessageManager.getString("label.paste_new_window"));
666 item.addActionListener(new ActionListener()
669 public void actionPerformed(ActionEvent evt)
676 popup.show(this, x, y);
683 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
684 Transferable contents = c.getContents(this);
686 if (contents != null)
688 String file = (String) contents
689 .getTransferData(DataFlavor.stringFlavor);
691 FileFormatI format = new IdentifyFile().identify(file,
692 DataSourceType.PASTE);
694 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
697 } catch (Exception ex)
700 .println("Unable to paste alignment from system clipboard:\n"
706 * Adds and opens the given frame to the desktop
717 public static synchronized void addInternalFrame(
718 final JInternalFrame frame, String title, int w, int h)
720 addInternalFrame(frame, title, true, w, h, true);
724 * Add an internal frame to the Jalview desktop
731 * When true, display frame immediately, otherwise, caller must call
732 * setVisible themselves.
738 public static synchronized void addInternalFrame(
739 final JInternalFrame frame, String title, boolean makeVisible,
742 addInternalFrame(frame, title, makeVisible, w, h, true);
746 * Add an internal frame to the Jalview desktop and make it visible
759 public static synchronized void addInternalFrame(
760 final JInternalFrame frame, String title, int w, int h,
763 addInternalFrame(frame, title, true, w, h, resizable);
767 * Add an internal frame to the Jalview desktop
774 * When true, display frame immediately, otherwise, caller must call
775 * setVisible themselves.
783 public static synchronized void addInternalFrame(
784 final JInternalFrame frame, String title, boolean makeVisible,
785 int w, int h, boolean resizable)
788 // TODO: allow callers to determine X and Y position of frame (eg. via
790 // TODO: consider fixing method to update entries in the window submenu with
791 // the current window title
793 frame.setTitle(title);
794 if (frame.getWidth() < 1 || frame.getHeight() < 1)
798 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
799 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
800 // IF JALVIEW IS RUNNING HEADLESS
801 // ///////////////////////////////////////////////
803 || (System.getProperty("java.awt.headless") != null && System
804 .getProperty("java.awt.headless").equals("true")))
811 frame.setVisible(makeVisible);
812 frame.setClosable(true);
813 frame.setResizable(resizable);
814 frame.setMaximizable(resizable);
815 frame.setIconifiable(resizable);
816 if (Platform.isAMac())
818 frame.setIconifiable(false);
819 frame.setFrameIcon(null);
820 // frame.setDesktopIcon(null);
821 frame.setDoubleBuffered(false);
823 if (frame.getX() < 1 && frame.getY() < 1)
825 frame.setLocation(xOffset * openFrameCount, yOffset
826 * ((openFrameCount - 1) % 10) + yOffset);
830 * add an entry for the new frame in the Window menu
831 * (and remove it when the frame is closed)
833 final JMenuItem menuItem = new JMenuItem(title);
834 frame.addInternalFrameListener(new InternalFrameAdapter()
837 public void internalFrameActivated(InternalFrameEvent evt)
839 JInternalFrame itf = desktop.getSelectedFrame();
847 public void internalFrameClosed(InternalFrameEvent evt)
849 PaintRefresher.RemoveComponent(frame);
852 * defensive check to prevent frames being
853 * added half off the window
855 if (openFrameCount > 0)
861 * ensure no reference to alignFrame retained by menu item listener
863 if (menuItem.getActionListeners().length > 0)
865 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
867 windowMenu.remove(menuItem);
868 JInternalFrame itf = desktop.getSelectedFrame();
872 if (itf instanceof AlignFrame)
874 Jalview.setCurrentAlignFrame((AlignFrame) itf);
881 menuItem.addActionListener(new ActionListener()
884 public void actionPerformed(ActionEvent e)
888 frame.setSelected(true);
889 frame.setIcon(false);
890 } catch (java.beans.PropertyVetoException ex)
897 windowMenu.add(menuItem);
903 frame.setSelected(true);
904 frame.requestFocus();
905 } catch (java.beans.PropertyVetoException ve)
907 } catch (java.lang.ClassCastException cex)
910 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
916 public void lostOwnership(Clipboard clipboard, Transferable contents)
920 Desktop.jalviewClipboard = null;
923 internalCopy = false;
927 public void dragEnter(DropTargetDragEvent evt)
932 public void dragExit(DropTargetEvent evt)
937 public void dragOver(DropTargetDragEvent evt)
942 public void dropActionChanged(DropTargetDragEvent evt)
953 public void drop(DropTargetDropEvent evt)
955 boolean success = true;
956 // JAL-1552 - acceptDrop required before getTransferable call for
957 // Java's Transferable for native dnd
958 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
959 Transferable t = evt.getTransferable();
960 List<String> files = new ArrayList<String>();
961 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
965 Desktop.transferFromDropTarget(files, protocols, evt, t);
966 } catch (Exception e)
976 for (int i = 0; i < files.size(); i++)
978 String file = files.get(i).toString();
979 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
981 FileFormatI format = null;
983 if (file.endsWith(".jar"))
985 format = FileFormat.Jalview;
990 format = new IdentifyFile().identify(file, protocol);
993 new FileLoader().LoadFile(file, protocol, format);
996 } catch (Exception ex)
1001 evt.dropComplete(success); // need this to ensure input focus is properly
1002 // transfered to any new windows created
1012 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1014 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1015 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1016 Cache.getProperty("LAST_DIRECTORY"),
1017 // AppletFormatAdapter.READABLE_EXTENSIONS,
1018 // AppletFormatAdapter.READABLE_FNAMES,
1021 chooser.setFileView(new JalviewFileView());
1022 chooser.setDialogTitle(MessageManager
1023 .getString("label.open_local_file"));
1024 chooser.setToolTipText(MessageManager.getString("action.open"));
1026 int value = chooser.showOpenDialog(this);
1028 if (value == JalviewFileChooser.APPROVE_OPTION)
1030 String choice = chooser.getSelectedFile().getPath();
1031 Cache.setProperty("LAST_DIRECTORY", chooser
1032 .getSelectedFile().getParent());
1034 FileFormatI format = null;
1035 FileFormatI selectedFormat = chooser.getSelectedFormat();
1036 if (FileFormat.Jalview.equals(selectedFormat))
1038 format = FileFormat.Jalview;
1044 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1045 } catch (FileFormatException e)
1051 if (viewport != null)
1053 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1058 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1070 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1072 // This construct allows us to have a wider textfield
1074 JLabel label = new JLabel(
1075 MessageManager.getString("label.input_file_url"));
1076 final JComboBox history = new JComboBox();
1078 JPanel panel = new JPanel(new GridLayout(2, 1));
1081 history.setPreferredSize(new Dimension(400, 20));
1082 history.setEditable(true);
1083 history.addItem("http://www.");
1085 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1089 if (historyItems != null)
1091 st = new StringTokenizer(historyItems, "\t");
1093 while (st.hasMoreTokens())
1095 history.addItem(st.nextElement());
1099 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1100 MessageManager.getString("label.input_alignment_from_url"),
1101 JvOptionPane.OK_CANCEL_OPTION);
1103 if (reply != JvOptionPane.OK_OPTION)
1108 String url = history.getSelectedItem().toString();
1110 if (url.toLowerCase().endsWith(".jar"))
1112 if (viewport != null)
1114 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1115 FileFormat.Jalview);
1119 new FileLoader().LoadFile(url, DataSourceType.URL,
1120 FileFormat.Jalview);
1125 FileFormatI format = null;
1128 format = new IdentifyFile().identify(url, DataSourceType.URL);
1129 } catch (FileFormatException e)
1131 // TODO revise error handling, distinguish between
1132 // URL not found and response not valid
1137 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1138 MessageManager.formatMessage("label.couldnt_locate",
1139 new Object[] { url }), MessageManager
1140 .getString("label.url_not_found"),
1141 JvOptionPane.WARNING_MESSAGE);
1146 if (viewport != null)
1149 .LoadFile(viewport, url, DataSourceType.URL, format);
1153 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1159 * Opens the CutAndPaste window for the user to paste an alignment in to
1162 * - if not null, the pasted alignment is added to the current
1163 * alignment; if null, to a new alignment window
1166 public void inputTextboxMenuItem_actionPerformed(
1167 AlignmentViewPanel viewPanel)
1169 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1170 cap.setForInput(viewPanel);
1171 Desktop.addInternalFrame(cap,
1172 MessageManager.getString("label.cut_paste_alignmen_file"),
1182 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1184 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1185 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1187 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1188 getBounds().y, getWidth(), getHeight()));
1190 if (jconsole != null)
1192 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1193 jconsole.stopConsole();
1197 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1200 if (dialogExecutor != null)
1202 dialogExecutor.shutdownNow();
1204 closeAll_actionPerformed(null);
1206 if (groovyConsole != null)
1208 // suppress a possible repeat prompt to save script
1209 groovyConsole.setDirty(false);
1210 groovyConsole.exit();
1215 private void storeLastKnownDimensions(String string, Rectangle jc)
1217 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1218 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1219 + " height:" + jc.height);
1221 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1222 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1223 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1224 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1234 public void aboutMenuItem_actionPerformed(ActionEvent e)
1236 // StringBuffer message = getAboutMessage(false);
1237 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1239 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1240 new Thread(new Runnable()
1245 new SplashScreen(true);
1250 public StringBuffer getAboutMessage(boolean shortv)
1252 StringBuffer message = new StringBuffer();
1253 message.append("<html>");
1256 message.append("<h1><strong>Version: "
1257 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1258 message.append("<strong>Last Updated: <em>"
1259 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1260 + "</em></strong>");
1266 message.append("<strong>Version "
1267 + jalview.bin.Cache.getProperty("VERSION")
1268 + "; last updated: "
1269 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1272 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1275 message.append("<br>...Checking latest version...</br>");
1277 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1278 .equals(jalview.bin.Cache.getProperty("VERSION")))
1280 boolean red = false;
1281 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1282 .indexOf("automated build") == -1)
1285 // Displayed when code version and jnlp version do not match and code
1286 // version is not a development build
1287 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1290 message.append("<br>!! Version "
1291 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1293 + " is available for download from "
1294 + jalview.bin.Cache.getDefault("www.jalview.org",
1295 "http://www.jalview.org") + " !!");
1298 message.append("</div>");
1301 message.append("<br>Authors: "
1303 .getDefault("AUTHORFNAMES",
1304 "The Jalview Authors (See AUTHORS file for current list)")
1305 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1306 + "<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"
1307 + "<br><br>If you use Jalview, please cite:"
1308 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1309 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1310 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1322 public void documentationMenuItem_actionPerformed(ActionEvent e)
1326 Help.showHelpWindow();
1327 } catch (Exception ex)
1333 public void closeAll_actionPerformed(ActionEvent e)
1335 // TODO show a progress bar while closing?
1336 JInternalFrame[] frames = desktop.getAllFrames();
1337 for (int i = 0; i < frames.length; i++)
1341 frames[i].setClosed(true);
1342 } catch (java.beans.PropertyVetoException ex)
1346 Jalview.setCurrentAlignFrame(null);
1347 System.out.println("ALL CLOSED");
1348 if (v_client != null)
1350 // TODO clear binding to vamsas document objects on close_all
1354 * reset state of singleton objects as appropriate (clear down session state
1355 * when all windows are closed)
1357 StructureSelectionManager ssm = StructureSelectionManager
1358 .getStructureSelectionManager(this);
1367 public void raiseRelated_actionPerformed(ActionEvent e)
1369 reorderAssociatedWindows(false, false);
1373 public void minimizeAssociated_actionPerformed(ActionEvent e)
1375 reorderAssociatedWindows(true, false);
1378 void closeAssociatedWindows()
1380 reorderAssociatedWindows(false, true);
1386 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1390 protected void garbageCollect_actionPerformed(ActionEvent e)
1392 // We simply collect the garbage
1393 jalview.bin.Cache.log.debug("Collecting garbage...");
1395 jalview.bin.Cache.log.debug("Finished garbage collection.");
1402 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1406 protected void showMemusage_actionPerformed(ActionEvent e)
1408 desktop.showMemoryUsage(showMemusage.isSelected());
1415 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1419 protected void showConsole_actionPerformed(ActionEvent e)
1421 showConsole(showConsole.isSelected());
1424 Console jconsole = null;
1427 * control whether the java console is visible or not
1431 void showConsole(boolean selected)
1433 showConsole.setSelected(selected);
1434 // TODO: decide if we should update properties file
1435 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1437 jconsole.setVisible(selected);
1440 void reorderAssociatedWindows(boolean minimize, boolean close)
1442 JInternalFrame[] frames = desktop.getAllFrames();
1443 if (frames == null || frames.length < 1)
1448 AlignmentViewport source = null, target = null;
1449 if (frames[0] instanceof AlignFrame)
1451 source = ((AlignFrame) frames[0]).getCurrentView();
1453 else if (frames[0] instanceof TreePanel)
1455 source = ((TreePanel) frames[0]).getViewPort();
1457 else if (frames[0] instanceof PCAPanel)
1459 source = ((PCAPanel) frames[0]).av;
1461 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1463 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1468 for (int i = 0; i < frames.length; i++)
1471 if (frames[i] == null)
1475 if (frames[i] instanceof AlignFrame)
1477 target = ((AlignFrame) frames[i]).getCurrentView();
1479 else if (frames[i] instanceof TreePanel)
1481 target = ((TreePanel) frames[i]).getViewPort();
1483 else if (frames[i] instanceof PCAPanel)
1485 target = ((PCAPanel) frames[i]).av;
1487 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1489 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1492 if (source == target)
1498 frames[i].setClosed(true);
1502 frames[i].setIcon(minimize);
1505 frames[i].toFront();
1509 } catch (java.beans.PropertyVetoException ex)
1524 protected void preferences_actionPerformed(ActionEvent e)
1536 public void saveState_actionPerformed(ActionEvent e)
1538 JalviewFileChooser chooser = new JalviewFileChooser(
1539 Cache.getProperty("LAST_DIRECTORY"), "jvp", "Jalview Project",
1542 chooser.setFileView(new JalviewFileView());
1543 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1545 int value = chooser.showSaveDialog(this);
1547 if (value == JalviewFileChooser.APPROVE_OPTION)
1549 final Desktop me = this;
1550 final java.io.File choice = chooser.getSelectedFile();
1551 setProjectFile(choice);
1553 new Thread(new Runnable()
1558 // TODO: refactor to Jalview desktop session controller action.
1559 setProgressBar(MessageManager.formatMessage(
1560 "label.saving_jalview_project",
1561 new Object[] { choice.getName() }), choice.hashCode());
1562 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1563 choice.getParent());
1564 // TODO catch and handle errors for savestate
1565 // TODO prevent user from messing with the Desktop whilst we're saving
1568 new Jalview2XML().saveState(choice);
1569 } catch (OutOfMemoryError oom)
1571 new OOMWarning("Whilst saving current state to "
1572 + choice.getName(), oom);
1573 } catch (Exception ex)
1576 "Problems whilst trying to save to " + choice.getName(),
1578 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1579 "label.error_whilst_saving_current_state_to",
1580 new Object[] { choice.getName() }), MessageManager
1581 .getString("label.couldnt_save_project"),
1582 JvOptionPane.WARNING_MESSAGE);
1584 setProgressBar(null, choice.hashCode());
1590 private void setProjectFile(File choice)
1592 this.projectFile = choice;
1595 public File getProjectFile()
1597 return this.projectFile;
1607 public void loadState_actionPerformed(ActionEvent e)
1609 JalviewFileChooser chooser = new JalviewFileChooser(
1610 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1611 "jvp", "jar" }, new String[] { "Jalview Project",
1612 "Jalview Project (old)" }, "Jalview Project");
1613 chooser.setFileView(new JalviewFileView());
1614 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1616 int value = chooser.showOpenDialog(this);
1618 if (value == JalviewFileChooser.APPROVE_OPTION)
1620 final File selectedFile = chooser.getSelectedFile();
1621 setProjectFile(selectedFile);
1622 final String choice = selectedFile.getAbsolutePath();
1623 Cache.setProperty("LAST_DIRECTORY",
1624 selectedFile.getParent());
1625 new Thread(new Runnable()
1631 MessageManager.formatMessage(
1632 "label.loading_jalview_project",
1633 new Object[] { choice }), choice.hashCode());
1636 new Jalview2XML().loadJalviewAlign(choice);
1637 } catch (OutOfMemoryError oom)
1639 new OOMWarning("Whilst loading project from " + choice, oom);
1640 } catch (Exception ex)
1642 Cache.log.error("Problems whilst loading project from "
1644 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1646 "label.error_whilst_loading_project_from",
1647 new Object[] { choice }), MessageManager
1648 .getString("label.couldnt_load_project"),
1649 JvOptionPane.WARNING_MESSAGE);
1651 setProgressBar(null, choice.hashCode());
1658 public void inputSequence_actionPerformed(ActionEvent e)
1660 new SequenceFetcher(this);
1663 JPanel progressPanel;
1665 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1667 public void startLoading(final String fileName)
1669 if (fileLoadingCount == 0)
1671 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1672 "label.loading_file", new Object[] { fileName })));
1677 private JPanel addProgressPanel(String string)
1679 if (progressPanel == null)
1681 progressPanel = new JPanel(new GridLayout(1, 1));
1682 totalProgressCount = 0;
1683 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1685 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1686 JProgressBar progressBar = new JProgressBar();
1687 progressBar.setIndeterminate(true);
1689 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1691 thisprogress.add(progressBar, BorderLayout.CENTER);
1692 progressPanel.add(thisprogress);
1693 ((GridLayout) progressPanel.getLayout())
1694 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1695 ++totalProgressCount;
1696 instance.validate();
1697 return thisprogress;
1700 int totalProgressCount = 0;
1702 private void removeProgressPanel(JPanel progbar)
1704 if (progressPanel != null)
1706 synchronized (progressPanel)
1708 progressPanel.remove(progbar);
1709 GridLayout gl = (GridLayout) progressPanel.getLayout();
1710 gl.setRows(gl.getRows() - 1);
1711 if (--totalProgressCount < 1)
1713 this.getContentPane().remove(progressPanel);
1714 progressPanel = null;
1721 public void stopLoading()
1724 if (fileLoadingCount < 1)
1726 while (fileLoadingPanels.size() > 0)
1728 removeProgressPanel(fileLoadingPanels.remove(0));
1730 fileLoadingPanels.clear();
1731 fileLoadingCount = 0;
1736 public static int getViewCount(String alignmentId)
1738 AlignmentViewport[] aps = getViewports(alignmentId);
1739 return (aps == null) ? 0 : aps.length;
1744 * @param alignmentId
1745 * - if null, all sets are returned
1746 * @return all AlignmentPanels concerning the alignmentId sequence set
1748 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1750 if (Desktop.desktop == null)
1752 // no frames created and in headless mode
1753 // TODO: verify that frames are recoverable when in headless mode
1756 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1757 AlignFrame[] frames = getAlignFrames();
1762 for (AlignFrame af : frames)
1764 for (AlignmentPanel ap : af.alignPanels)
1766 if (alignmentId == null
1767 || alignmentId.equals(ap.av.getSequenceSetId()))
1773 if (aps.size() == 0)
1777 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1782 * get all the viewports on an alignment.
1784 * @param sequenceSetId
1785 * unique alignment id (may be null - all viewports returned in that
1787 * @return all viewports on the alignment bound to sequenceSetId
1789 public static AlignmentViewport[] getViewports(String sequenceSetId)
1791 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1792 if (desktop != null)
1794 AlignFrame[] frames = Desktop.getAlignFrames();
1796 for (AlignFrame afr : frames)
1798 if (sequenceSetId == null
1799 || afr.getViewport().getSequenceSetId()
1800 .equals(sequenceSetId))
1802 if (afr.alignPanels != null)
1804 for (AlignmentPanel ap : afr.alignPanels)
1806 if (sequenceSetId == null
1807 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1815 viewp.add(afr.getViewport());
1819 if (viewp.size() > 0)
1821 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1828 * Explode the views in the given frame into separate AlignFrame
1832 public static void explodeViews(AlignFrame af)
1834 int size = af.alignPanels.size();
1840 for (int i = 0; i < size; i++)
1842 AlignmentPanel ap = af.alignPanels.get(i);
1843 AlignFrame newaf = new AlignFrame(ap);
1846 * Restore the view's last exploded frame geometry if known. Multiple
1847 * views from one exploded frame share and restore the same (frame)
1848 * position and size.
1850 Rectangle geometry = ap.av.getExplodedGeometry();
1851 if (geometry != null)
1853 newaf.setBounds(geometry);
1856 ap.av.setGatherViewsHere(false);
1858 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1859 AlignFrame.DEFAULT_HEIGHT);
1862 af.alignPanels.clear();
1863 af.closeMenuItem_actionPerformed(true);
1868 * Gather expanded views (separate AlignFrame's) with the same sequence set
1869 * identifier back in to this frame as additional views, and close the
1870 * expanded views. Note the expanded frames may themselves have multiple
1871 * views. We take the lot.
1875 public void gatherViews(AlignFrame source)
1877 source.viewport.setGatherViewsHere(true);
1878 source.viewport.setExplodedGeometry(source.getBounds());
1879 JInternalFrame[] frames = desktop.getAllFrames();
1880 String viewId = source.viewport.getSequenceSetId();
1882 for (int t = 0; t < frames.length; t++)
1884 if (frames[t] instanceof AlignFrame && frames[t] != source)
1886 AlignFrame af = (AlignFrame) frames[t];
1887 boolean gatherThis = false;
1888 for (int a = 0; a < af.alignPanels.size(); a++)
1890 AlignmentPanel ap = af.alignPanels.get(a);
1891 if (viewId.equals(ap.av.getSequenceSetId()))
1894 ap.av.setGatherViewsHere(false);
1895 ap.av.setExplodedGeometry(af.getBounds());
1896 source.addAlignmentPanel(ap, false);
1902 af.alignPanels.clear();
1903 af.closeMenuItem_actionPerformed(true);
1910 jalview.gui.VamsasApplication v_client = null;
1913 public void vamsasImport_actionPerformed(ActionEvent e)
1915 if (v_client == null)
1917 // Load and try to start a session.
1918 JalviewFileChooser chooser = new JalviewFileChooser(
1919 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1921 chooser.setFileView(new JalviewFileView());
1922 chooser.setDialogTitle(MessageManager
1923 .getString("label.open_saved_vamsas_session"));
1924 chooser.setToolTipText(MessageManager
1925 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1927 int value = chooser.showOpenDialog(this);
1929 if (value == JalviewFileChooser.APPROVE_OPTION)
1931 String fle = chooser.getSelectedFile().toString();
1932 if (!vamsasImport(chooser.getSelectedFile()))
1935 .showInternalMessageDialog(
1937 MessageManager.formatMessage(
1938 "label.couldnt_import_as_vamsas_session",
1939 new Object[] { fle }),
1941 .getString("label.vamsas_document_import_failed"),
1942 JvOptionPane.ERROR_MESSAGE);
1948 jalview.bin.Cache.log
1949 .error("Implementation error - load session from a running session is not supported.");
1954 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1957 * @return true if import was a success and a session was started.
1959 public boolean vamsasImport(URL url)
1961 // TODO: create progress bar
1962 if (v_client != null)
1965 jalview.bin.Cache.log
1966 .error("Implementation error - load session from a running session is not supported.");
1972 // copy the URL content to a temporary local file
1973 // TODO: be a bit cleverer here with nio (?!)
1974 File file = File.createTempFile("vdocfromurl", ".vdj");
1975 FileOutputStream fos = new FileOutputStream(file);
1976 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1977 byte[] buffer = new byte[2048];
1979 while ((ln = bis.read(buffer)) > -1)
1981 fos.write(buffer, 0, ln);
1985 v_client = new jalview.gui.VamsasApplication(this, file,
1986 url.toExternalForm());
1987 } catch (Exception ex)
1989 jalview.bin.Cache.log.error(
1990 "Failed to create new vamsas session from contents of URL "
1994 setupVamsasConnectedGui();
1995 v_client.initial_update(); // TODO: thread ?
1996 return v_client.inSession();
2000 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2003 * @return true if import was a success and a session was started.
2005 public boolean vamsasImport(File file)
2007 if (v_client != null)
2010 jalview.bin.Cache.log
2011 .error("Implementation error - load session from a running session is not supported.");
2015 setProgressBar(MessageManager.formatMessage(
2016 "status.importing_vamsas_session_from",
2017 new Object[] { file.getName() }), file.hashCode());
2020 v_client = new jalview.gui.VamsasApplication(this, file, null);
2021 } catch (Exception ex)
2023 setProgressBar(MessageManager.formatMessage(
2024 "status.importing_vamsas_session_from",
2025 new Object[] { file.getName() }), file.hashCode());
2026 jalview.bin.Cache.log.error(
2027 "New vamsas session from existing session file failed:", ex);
2030 setupVamsasConnectedGui();
2031 v_client.initial_update(); // TODO: thread ?
2032 setProgressBar(MessageManager.formatMessage(
2033 "status.importing_vamsas_session_from",
2034 new Object[] { file.getName() }), file.hashCode());
2035 return v_client.inSession();
2038 public boolean joinVamsasSession(String mysesid)
2040 if (v_client != null)
2044 .getString("error.try_join_vamsas_session_another"));
2046 if (mysesid == null)
2049 MessageManager.getString("error.invalid_vamsas_session_id"));
2051 v_client = new VamsasApplication(this, mysesid);
2052 setupVamsasConnectedGui();
2053 v_client.initial_update();
2054 return (v_client.inSession());
2058 public void vamsasStart_actionPerformed(ActionEvent e)
2060 if (v_client == null)
2063 // we just start a default session for moment.
2065 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2066 * getProperty("LAST_DIRECTORY"));
2068 * chooser.setFileView(new JalviewFileView());
2069 * chooser.setDialogTitle("Load Vamsas file");
2070 * chooser.setToolTipText("Import");
2072 * int value = chooser.showOpenDialog(this);
2074 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2075 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2077 v_client = new VamsasApplication(this);
2078 setupVamsasConnectedGui();
2079 v_client.initial_update(); // TODO: thread ?
2083 // store current data in session.
2084 v_client.push_update(); // TODO: thread
2088 protected void setupVamsasConnectedGui()
2090 vamsasStart.setText(MessageManager.getString("label.session_update"));
2091 vamsasSave.setVisible(true);
2092 vamsasStop.setVisible(true);
2093 vamsasImport.setVisible(false); // Document import to existing session is
2094 // not possible for vamsas-client-1.0.
2097 protected void setupVamsasDisconnectedGui()
2099 vamsasSave.setVisible(false);
2100 vamsasStop.setVisible(false);
2101 vamsasImport.setVisible(true);
2102 vamsasStart.setText(MessageManager
2103 .getString("label.new_vamsas_session"));
2107 public void vamsasStop_actionPerformed(ActionEvent e)
2109 if (v_client != null)
2111 v_client.end_session();
2113 setupVamsasDisconnectedGui();
2117 protected void buildVamsasStMenu()
2119 if (v_client == null)
2121 String[] sess = null;
2124 sess = VamsasApplication.getSessionList();
2125 } catch (Exception e)
2127 jalview.bin.Cache.log.warn(
2128 "Problem getting current sessions list.", e);
2133 jalview.bin.Cache.log.debug("Got current sessions list: "
2134 + sess.length + " entries.");
2135 VamsasStMenu.removeAll();
2136 for (int i = 0; i < sess.length; i++)
2138 JMenuItem sessit = new JMenuItem();
2139 sessit.setText(sess[i]);
2140 sessit.setToolTipText(MessageManager.formatMessage(
2141 "label.connect_to_session", new Object[] { sess[i] }));
2142 final Desktop dsktp = this;
2143 final String mysesid = sess[i];
2144 sessit.addActionListener(new ActionListener()
2148 public void actionPerformed(ActionEvent e)
2150 if (dsktp.v_client == null)
2152 Thread rthr = new Thread(new Runnable()
2158 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2159 dsktp.setupVamsasConnectedGui();
2160 dsktp.v_client.initial_update();
2168 VamsasStMenu.add(sessit);
2170 // don't show an empty menu.
2171 VamsasStMenu.setVisible(sess.length > 0);
2176 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2177 VamsasStMenu.removeAll();
2178 VamsasStMenu.setVisible(false);
2183 // Not interested in the content. Just hide ourselves.
2184 VamsasStMenu.setVisible(false);
2189 public void vamsasSave_actionPerformed(ActionEvent e)
2191 if (v_client != null)
2193 JalviewFileChooser chooser = new JalviewFileChooser(
2194 Cache.getProperty("LAST_DIRECTORY"), "vdj",// TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2195 "Vamsas Document", "Vamsas Document");
2197 chooser.setFileView(new JalviewFileView());
2198 chooser.setDialogTitle(MessageManager
2199 .getString("label.save_vamsas_document_archive"));
2201 int value = chooser.showSaveDialog(this);
2203 if (value == JalviewFileChooser.APPROVE_OPTION)
2205 java.io.File choice = chooser.getSelectedFile();
2206 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2207 "label.saving_vamsas_doc",
2208 new Object[] { choice.getName() }));
2209 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2210 String warnmsg = null;
2211 String warnttl = null;
2214 v_client.vclient.storeDocument(choice);
2217 warnttl = "Serious Problem saving Vamsas Document";
2218 warnmsg = ex.toString();
2219 jalview.bin.Cache.log.error("Error Whilst saving document to "
2222 } catch (Exception ex)
2224 warnttl = "Problem saving Vamsas Document.";
2225 warnmsg = ex.toString();
2226 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2230 removeProgressPanel(progpanel);
2231 if (warnmsg != null)
2233 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2235 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2241 JPanel vamUpdate = null;
2244 * hide vamsas user gui bits when a vamsas document event is being handled.
2247 * true to hide gui, false to reveal gui
2249 public void setVamsasUpdate(boolean b)
2251 Cache.log.debug("Setting gui for Vamsas update "
2252 + (b ? "in progress" : "finished"));
2254 if (vamUpdate != null)
2256 this.removeProgressPanel(vamUpdate);
2260 vamUpdate = this.addProgressPanel(MessageManager
2261 .getString("label.updating_vamsas_session"));
2263 vamsasStart.setVisible(!b);
2264 vamsasStop.setVisible(!b);
2265 vamsasSave.setVisible(!b);
2268 public JInternalFrame[] getAllFrames()
2270 return desktop.getAllFrames();
2274 * Checks the given url to see if it gives a response indicating that the user
2275 * should be informed of a new questionnaire.
2279 public void checkForQuestionnaire(String url)
2281 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2282 // javax.swing.SwingUtilities.invokeLater(jvq);
2283 new Thread(jvq).start();
2286 public void checkURLLinks()
2288 // Thread off the URL link checker
2289 addDialogThread(new Runnable()
2294 if (Cache.getDefault("CHECKURLLINKS", true))
2296 // check what the actual links are - if it's just the default don't
2297 // bother with the warning
2298 Vector<String> links = Preferences.sequenceURLLinks;
2300 // only need to check links if there is one with a
2301 // SEQUENCE_ID which is not the default EMBL_EBI link
2302 ListIterator<String> li = links.listIterator();
2303 boolean check = false;
2304 List<JLabel> urls = new ArrayList<JLabel>();
2305 while (li.hasNext())
2307 String link = li.next();
2308 if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
2311 int barPos = link.indexOf("|");
2312 String urlMsg = barPos == -1 ? link : link.substring(0,
2313 barPos) + ": " + link.substring(barPos + 1);
2314 urls.add(new JLabel(urlMsg));
2322 // ask user to check in case URL links use old style tokens
2323 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2324 JPanel msgPanel = new JPanel();
2325 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2326 msgPanel.add(Box.createVerticalGlue());
2327 JLabel msg = new JLabel(
2329 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2330 JLabel msg2 = new JLabel(
2332 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2334 for (JLabel url : urls)
2340 final JCheckBox jcb = new JCheckBox(
2341 MessageManager.getString("label.do_not_display_again"));
2342 jcb.addActionListener(new ActionListener()
2345 public void actionPerformed(ActionEvent e)
2347 // update Cache settings for "don't show this again"
2348 boolean showWarningAgain = !jcb.isSelected();
2349 Cache.setProperty("CHECKURLLINKS",
2350 Boolean.valueOf(showWarningAgain).toString());
2355 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2357 .getString("label.SEQUENCE_ID_no_longer_used"),
2358 JvOptionPane.WARNING_MESSAGE);
2365 * Proxy class for JDesktopPane which optionally displays the current memory
2366 * usage and highlights the desktop area with a red bar if free memory runs
2371 public class MyDesktopPane extends JDesktopPane implements Runnable
2374 private static final float ONE_MB = 1048576f;
2376 boolean showMemoryUsage = false;
2380 java.text.NumberFormat df;
2382 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2385 public MyDesktopPane(boolean showMemoryUsage)
2387 showMemoryUsage(showMemoryUsage);
2390 public void showMemoryUsage(boolean showMemory)
2392 this.showMemoryUsage = showMemory;
2395 Thread worker = new Thread(this);
2400 public boolean isShowMemoryUsage()
2402 return showMemoryUsage;
2408 df = java.text.NumberFormat.getNumberInstance();
2409 df.setMaximumFractionDigits(2);
2410 runtime = Runtime.getRuntime();
2412 while (showMemoryUsage)
2416 maxMemory = runtime.maxMemory() / ONE_MB;
2417 allocatedMemory = runtime.totalMemory() / ONE_MB;
2418 freeMemory = runtime.freeMemory() / ONE_MB;
2419 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2421 percentUsage = (totalFreeMemory / maxMemory) * 100;
2423 // if (percentUsage < 20)
2425 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2427 // instance.set.setBorder(border1);
2430 // sleep after showing usage
2432 } catch (Exception ex)
2434 ex.printStackTrace();
2440 public void paintComponent(Graphics g)
2442 if (showMemoryUsage && g != null && df != null)
2444 if (percentUsage < 20)
2446 g.setColor(Color.red);
2448 FontMetrics fm = g.getFontMetrics();
2451 g.drawString(MessageManager.formatMessage(
2452 "label.memory_stats",
2453 new Object[] { df.format(totalFreeMemory),
2454 df.format(maxMemory), df.format(percentUsage) }), 10,
2455 getHeight() - fm.getHeight());
2462 * fixes stacking order after a modal dialog to ensure windows that should be
2463 * on top actually are
2465 public void relayerWindows()
2470 protected JMenuItem groovyShell;
2473 * Accessor method to quickly get all the AlignmentFrames loaded.
2475 * @return an array of AlignFrame, or null if none found
2477 public static AlignFrame[] getAlignFrames()
2479 if (Jalview.isHeadlessMode())
2481 // Desktop.desktop is null in headless mode
2482 return new AlignFrame[] { Jalview.currentAlignFrame };
2485 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2491 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2493 for (int i = frames.length - 1; i > -1; i--)
2495 if (frames[i] instanceof AlignFrame)
2497 avp.add((AlignFrame) frames[i]);
2499 else if (frames[i] instanceof SplitFrame)
2502 * Also check for a split frame containing an AlignFrame
2504 GSplitFrame sf = (GSplitFrame) frames[i];
2505 if (sf.getTopFrame() instanceof AlignFrame)
2507 avp.add((AlignFrame) sf.getTopFrame());
2509 if (sf.getBottomFrame() instanceof AlignFrame)
2511 avp.add((AlignFrame) sf.getBottomFrame());
2515 if (avp.size() == 0)
2519 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2524 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2528 public GStructureViewer[] getJmols()
2530 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2536 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2538 for (int i = frames.length - 1; i > -1; i--)
2540 if (frames[i] instanceof AppJmol)
2542 GStructureViewer af = (GStructureViewer) frames[i];
2546 if (avp.size() == 0)
2550 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2555 * Add Groovy Support to Jalview
2557 public void groovyShell_actionPerformed()
2561 openGroovyConsole();
2562 } catch (Exception ex)
2564 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2565 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2567 MessageManager.getString("label.couldnt_create_groovy_shell"),
2568 MessageManager.getString("label.groovy_support_failed"),
2569 JvOptionPane.ERROR_MESSAGE);
2574 * Open the Groovy console
2576 void openGroovyConsole()
2578 if (groovyConsole == null)
2580 groovyConsole = new groovy.ui.Console();
2581 groovyConsole.setVariable("Jalview", this);
2582 groovyConsole.run();
2585 * We allow only one console at a time, so that AlignFrame menu option
2586 * 'Calculate | Run Groovy script' is unambiguous.
2587 * Disable 'Groovy Console', and enable 'Run script', when the console is
2588 * opened, and the reverse when it is closed
2590 Window window = (Window) groovyConsole.getFrame();
2591 window.addWindowListener(new WindowAdapter()
2594 public void windowClosed(WindowEvent e)
2597 * rebind CMD-Q from Groovy Console to Jalview Quit
2600 enableExecuteGroovy(false);
2606 * show Groovy console window (after close and reopen)
2608 ((Window) groovyConsole.getFrame()).setVisible(true);
2611 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2612 * and disable opening a second console
2614 enableExecuteGroovy(true);
2618 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2619 * binding when opened
2621 protected void addQuitHandler()
2623 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2624 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2625 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2626 getRootPane().getActionMap().put("Quit", new AbstractAction()
2629 public void actionPerformed(ActionEvent e)
2637 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2640 * true if Groovy console is open
2642 public void enableExecuteGroovy(boolean enabled)
2645 * disable opening a second Groovy console
2646 * (or re-enable when the console is closed)
2648 groovyShell.setEnabled(!enabled);
2650 AlignFrame[] alignFrames = getAlignFrames();
2651 if (alignFrames != null)
2653 for (AlignFrame af : alignFrames)
2655 af.setGroovyEnabled(enabled);
2661 * Progress bars managed by the IProgressIndicator method.
2663 private Hashtable<Long, JPanel> progressBars;
2665 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2670 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2673 public void setProgressBar(String message, long id)
2675 if (progressBars == null)
2677 progressBars = new Hashtable<Long, JPanel>();
2678 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2681 if (progressBars.get(new Long(id)) != null)
2683 JPanel panel = progressBars.remove(new Long(id));
2684 if (progressBarHandlers.contains(new Long(id)))
2686 progressBarHandlers.remove(new Long(id));
2688 removeProgressPanel(panel);
2692 progressBars.put(new Long(id), addProgressPanel(message));
2699 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2700 * jalview.gui.IProgressIndicatorHandler)
2703 public void registerHandler(final long id,
2704 final IProgressIndicatorHandler handler)
2706 if (progressBarHandlers == null
2707 || !progressBars.containsKey(new Long(id)))
2711 .getString("error.call_setprogressbar_before_registering_handler"));
2713 progressBarHandlers.put(new Long(id), handler);
2714 final JPanel progressPanel = progressBars.get(new Long(id));
2715 if (handler.canCancel())
2717 JButton cancel = new JButton(
2718 MessageManager.getString("action.cancel"));
2719 final IProgressIndicator us = this;
2720 cancel.addActionListener(new ActionListener()
2724 public void actionPerformed(ActionEvent e)
2726 handler.cancelActivity(id);
2727 us.setProgressBar(MessageManager.formatMessage(
2728 "label.cancelled_params",
2729 new Object[] { ((JLabel) progressPanel.getComponent(0))
2733 progressPanel.add(cancel, BorderLayout.EAST);
2739 * @return true if any progress bars are still active
2742 public boolean operationInProgress()
2744 if (progressBars != null && progressBars.size() > 0)
2752 * This will return the first AlignFrame holding the given viewport instance.
2753 * It will break if there are more than one AlignFrames viewing a particular
2757 * @return alignFrame for viewport
2759 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2761 if (desktop != null)
2763 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2764 for (int panel = 0; aps != null && panel < aps.length; panel++)
2766 if (aps[panel] != null && aps[panel].av == viewport)
2768 return aps[panel].alignFrame;
2775 public VamsasApplication getVamsasApplication()
2782 * flag set if jalview GUI is being operated programmatically
2784 private boolean inBatchMode = false;
2787 * check if jalview GUI is being operated programmatically
2789 * @return inBatchMode
2791 public boolean isInBatchMode()
2797 * set flag if jalview GUI is being operated programmatically
2799 * @param inBatchMode
2801 public void setInBatchMode(boolean inBatchMode)
2803 this.inBatchMode = inBatchMode;
2806 public void startServiceDiscovery()
2808 startServiceDiscovery(false);
2811 public void startServiceDiscovery(boolean blocking)
2813 boolean alive = true;
2814 Thread t0 = null, t1 = null, t2 = null;
2815 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2818 // todo: changesupport handlers need to be transferred
2819 if (discoverer == null)
2821 discoverer = new jalview.ws.jws1.Discoverer();
2822 // register PCS handler for desktop.
2823 discoverer.addPropertyChangeListener(changeSupport);
2825 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2826 // until we phase out completely
2827 (t0 = new Thread(discoverer)).start();
2830 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2832 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2834 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2836 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2842 // TODO: do rest service discovery
2851 } catch (Exception e)
2854 alive = (t1 != null && t1.isAlive())
2855 || (t2 != null && t2.isAlive())
2856 || (t3 != null && t3.isAlive())
2857 || (t0 != null && t0.isAlive());
2863 * called to check if the service discovery process completed successfully.
2867 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2869 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2871 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2872 .getErrorMessages();
2875 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2877 if (serviceChangedDialog == null)
2879 // only run if we aren't already displaying one of these.
2880 addDialogThread(serviceChangedDialog = new Runnable()
2887 * JalviewDialog jd =new JalviewDialog() {
2889 * @Override protected void cancelPressed() { // TODO
2890 * Auto-generated method stub
2892 * }@Override protected void okPressed() { // TODO
2893 * Auto-generated method stub
2895 * }@Override protected void raiseClosed() { // TODO
2896 * Auto-generated method stub
2898 * } }; jd.initDialogFrame(new
2899 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2900 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2901 * + " or mis-configured HTTP proxy settings.<br/>" +
2902 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2904 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2905 * ), true, true, "Web Service Configuration Problem", 450,
2908 * jd.waitForInput();
2914 "<html><table width=\"450\"><tr><td>"
2916 + "</td></tr></table>"
2917 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2918 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2919 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2920 + " Tools->Preferences dialog box to change them.</p></html>"),
2921 "Web Service Configuration Problem",
2922 JvOptionPane.DEFAULT_OPTION,
2923 JvOptionPane.ERROR_MESSAGE);
2924 serviceChangedDialog = null;
2933 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2940 private Runnable serviceChangedDialog = null;
2943 * start a thread to open a URL in the configured browser. Pops up a warning
2944 * dialog to the user if there is an exception when calling out to the browser
2949 public static void showUrl(final String url)
2951 showUrl(url, Desktop.instance);
2955 * Like showUrl but allows progress handler to be specified
2959 * (null) or object implementing IProgressIndicator
2961 public static void showUrl(final String url,
2962 final IProgressIndicator progress)
2964 new Thread(new Runnable()
2971 if (progress != null)
2973 progress.setProgressBar(MessageManager.formatMessage(
2974 "status.opening_params", new Object[] { url }), this
2977 jalview.util.BrowserLauncher.openURL(url);
2978 } catch (Exception ex)
2980 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2982 .getString("label.web_browser_not_found_unix"),
2983 MessageManager.getString("label.web_browser_not_found"),
2984 JvOptionPane.WARNING_MESSAGE);
2986 ex.printStackTrace();
2988 if (progress != null)
2990 progress.setProgressBar(null, this.hashCode());
2996 public static WsParamSetManager wsparamManager = null;
2998 public static ParamManager getUserParameterStore()
3000 if (wsparamManager == null)
3002 wsparamManager = new WsParamSetManager();
3004 return wsparamManager;
3008 * static hyperlink handler proxy method for use by Jalview's internal windows
3012 public static void hyperlinkUpdate(HyperlinkEvent e)
3014 if (e.getEventType() == EventType.ACTIVATED)
3019 url = e.getURL().toString();
3020 Desktop.showUrl(url);
3021 } catch (Exception x)
3025 if (Cache.log != null)
3027 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3031 System.err.println("Couldn't handle string " + url
3035 // ignore any exceptions due to dud links.
3042 * single thread that handles display of dialogs to user.
3044 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3047 * flag indicating if dialogExecutor should try to acquire a permit
3049 private volatile boolean dialogPause = true;
3054 private java.util.concurrent.Semaphore block = new Semaphore(0);
3056 private static groovy.ui.Console groovyConsole;
3059 * add another dialog thread to the queue
3063 public void addDialogThread(final Runnable prompter)
3065 dialogExecutor.submit(new Runnable()
3075 } catch (InterruptedException x)
3080 if (instance == null)
3086 SwingUtilities.invokeAndWait(prompter);
3087 } catch (Exception q)
3089 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3095 public void startDialogQueue()
3097 // set the flag so we don't pause waiting for another permit and semaphore
3098 // the current task to begin
3099 dialogPause = false;
3104 protected void snapShotWindow_actionPerformed(ActionEvent e)
3108 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3109 "View of Desktop", getWidth(), getHeight(), of = new File(
3110 "Jalview_snapshot" + System.currentTimeMillis()
3111 + ".eps"), "View of desktop", null, 0, false);
3114 paintAll(im.getGraphics());
3116 } catch (Exception q)
3118 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3122 Cache.log.info("Successfully written snapshot to file "
3123 + of.getAbsolutePath());
3127 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3128 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3129 * and location last time the view was expanded (if any). However it does not
3130 * remember the split pane divider location - this is set to match the
3131 * 'exploding' frame.
3135 public void explodeViews(SplitFrame sf)
3137 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3138 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3139 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3141 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3143 int viewCount = topPanels.size();
3150 * Processing in reverse order works, forwards order leaves the first panels
3151 * not visible. I don't know why!
3153 for (int i = viewCount - 1; i >= 0; i--)
3156 * Make new top and bottom frames. These take over the respective
3157 * AlignmentPanel objects, including their AlignmentViewports, so the
3158 * cdna/protein relationships between the viewports is carried over to the
3161 * explodedGeometry holds the (x, y) position of the previously exploded
3162 * SplitFrame, and the (width, height) of the AlignFrame component
3164 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3165 AlignFrame newTopFrame = new AlignFrame(topPanel);
3166 newTopFrame.setSize(oldTopFrame.getSize());
3167 newTopFrame.setVisible(true);
3168 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3169 .getExplodedGeometry();
3170 if (geometry != null)
3172 newTopFrame.setSize(geometry.getSize());
3175 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3176 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3177 newBottomFrame.setSize(oldBottomFrame.getSize());
3178 newBottomFrame.setVisible(true);
3179 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3180 .getExplodedGeometry();
3181 if (geometry != null)
3183 newBottomFrame.setSize(geometry.getSize());
3186 topPanel.av.setGatherViewsHere(false);
3187 bottomPanel.av.setGatherViewsHere(false);
3188 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3190 if (geometry != null)
3192 splitFrame.setLocation(geometry.getLocation());
3194 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3198 * Clear references to the panels (now relocated in the new SplitFrames)
3199 * before closing the old SplitFrame.
3202 bottomPanels.clear();
3207 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3208 * back into the given SplitFrame as additional views. Note that the gathered
3209 * frames may themselves have multiple views.
3213 public void gatherViews(GSplitFrame source)
3216 * special handling of explodedGeometry for a view within a SplitFrame: - it
3217 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3218 * height) of the AlignFrame component
3220 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3221 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3222 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3223 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3224 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3225 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3227 myTopFrame.viewport.setGatherViewsHere(true);
3228 myBottomFrame.viewport.setGatherViewsHere(true);
3229 String topViewId = myTopFrame.viewport.getSequenceSetId();
3230 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3232 JInternalFrame[] frames = desktop.getAllFrames();
3233 for (JInternalFrame frame : frames)
3235 if (frame instanceof SplitFrame && frame != source)
3237 SplitFrame sf = (SplitFrame) frame;
3238 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3239 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3240 boolean gatherThis = false;
3241 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3243 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3244 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3245 if (topViewId.equals(topPanel.av.getSequenceSetId())
3246 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3249 topPanel.av.setGatherViewsHere(false);
3250 bottomPanel.av.setGatherViewsHere(false);
3251 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3252 topFrame.getSize()));
3253 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3254 .getLocation(), bottomFrame.getSize()));
3255 myTopFrame.addAlignmentPanel(topPanel, false);
3256 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3262 topFrame.getAlignPanels().clear();
3263 bottomFrame.getAlignPanels().clear();
3270 * The dust settles...give focus to the tab we did this from.
3272 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3275 public static groovy.ui.Console getGroovyConsole()
3277 return groovyConsole;
3280 public static void transferFromDropTarget(List<String> files,
3281 List<DataSourceType> protocols, DropTargetDropEvent evt,
3286 DataFlavor uriListFlavor = new DataFlavor(
3287 "text/uri-list;class=java.lang.String");
3288 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3290 // Works on Windows and MacOSX
3291 Cache.log.debug("Drop handled as javaFileListFlavor");
3292 for (Object file : (List) t
3293 .getTransferData(DataFlavor.javaFileListFlavor))
3295 files.add(((File) file).toString());
3296 protocols.add(DataSourceType.FILE);
3301 // Unix like behaviour
3302 boolean added = false;
3304 if (t.isDataFlavorSupported(uriListFlavor))
3306 Cache.log.debug("Drop handled as uriListFlavor");
3307 // This is used by Unix drag system
3308 data = (String) t.getTransferData(uriListFlavor);
3312 // fallback to text: workaround - on OSX where there's a JVM bug
3313 Cache.log.debug("standard URIListFlavor failed. Trying text");
3314 // try text fallback
3315 data = (String) t.getTransferData(new DataFlavor(
3316 "text/plain;class=java.lang.String"));
3317 if (Cache.log.isDebugEnabled())
3319 Cache.log.debug("fallback returned " + data);
3322 while (protocols.size() < files.size())
3324 Cache.log.debug("Adding missing FILE protocol for "
3325 + files.get(protocols.size()));
3326 protocols.add(DataSourceType.FILE);
3328 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3329 data, "\r\n"); st.hasMoreTokens();)
3332 String s = st.nextToken();
3333 if (s.startsWith("#"))
3335 // the line is a comment (as per the RFC 2483)
3338 java.net.URI uri = new java.net.URI(s);
3339 if (uri.getScheme().toLowerCase().startsWith("http"))
3341 protocols.add(DataSourceType.URL);
3342 files.add(uri.toString());
3346 // otherwise preserve old behaviour: catch all for file objects
3347 java.io.File file = new java.io.File(uri);
3348 protocols.add(DataSourceType.FILE);
3349 files.add(file.toString());
3352 if (Cache.log.isDebugEnabled())
3354 if (data == null || !added)
3357 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3358 for (DataFlavor fl : t.getTransferDataFlavors())
3360 Cache.log.debug("Supported transfer dataflavor: "
3362 Object df = t.getTransferData(fl);
3365 Cache.log.debug("Retrieves: " + df);
3369 Cache.log.debug("Retrieved nothing");