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.FileFormats;
35 import jalview.io.FileLoader;
36 import jalview.io.IdentifyFile;
37 import jalview.io.JalviewFileChooser;
38 import jalview.io.JalviewFileView;
39 import jalview.jbgui.GSplitFrame;
40 import jalview.jbgui.GStructureViewer;
41 import jalview.structure.StructureSelectionManager;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.viewmodel.AlignmentViewport;
46 import jalview.ws.params.ParamManager;
48 import java.awt.BorderLayout;
49 import java.awt.Color;
50 import java.awt.Dimension;
51 import java.awt.FontMetrics;
52 import java.awt.Graphics;
53 import java.awt.GridLayout;
54 import java.awt.Point;
55 import java.awt.Rectangle;
56 import java.awt.Toolkit;
57 import java.awt.Window;
58 import java.awt.datatransfer.Clipboard;
59 import java.awt.datatransfer.ClipboardOwner;
60 import java.awt.datatransfer.DataFlavor;
61 import java.awt.datatransfer.Transferable;
62 import java.awt.dnd.DnDConstants;
63 import java.awt.dnd.DropTargetDragEvent;
64 import java.awt.dnd.DropTargetDropEvent;
65 import java.awt.dnd.DropTargetEvent;
66 import java.awt.dnd.DropTargetListener;
67 import java.awt.event.ActionEvent;
68 import java.awt.event.ActionListener;
69 import java.awt.event.FocusEvent;
70 import java.awt.event.FocusListener;
71 import java.awt.event.KeyEvent;
72 import java.awt.event.MouseAdapter;
73 import java.awt.event.MouseEvent;
74 import java.awt.event.WindowAdapter;
75 import java.awt.event.WindowEvent;
76 import java.beans.PropertyChangeEvent;
77 import java.beans.PropertyChangeListener;
78 import java.io.BufferedInputStream;
80 import java.io.FileOutputStream;
82 import java.util.ArrayList;
83 import java.util.Hashtable;
84 import java.util.List;
85 import java.util.ListIterator;
86 import java.util.StringTokenizer;
87 import java.util.Vector;
88 import java.util.concurrent.ExecutorService;
89 import java.util.concurrent.Executors;
90 import java.util.concurrent.Semaphore;
92 import javax.swing.AbstractAction;
93 import javax.swing.Box;
94 import javax.swing.BoxLayout;
95 import javax.swing.DefaultDesktopManager;
96 import javax.swing.DesktopManager;
97 import javax.swing.JButton;
98 import javax.swing.JCheckBox;
99 import javax.swing.JComboBox;
100 import javax.swing.JComponent;
101 import javax.swing.JDesktopPane;
102 import javax.swing.JFrame;
103 import javax.swing.JInternalFrame;
104 import javax.swing.JLabel;
105 import javax.swing.JMenuItem;
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()
458 // Thread off a new instance of the file chooser - this reduces the time it
459 // takes to open it later on.
460 new Thread(new Runnable()
465 Cache.log.debug("Filechooser init thread started.");
466 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
467 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
469 Cache.log.debug("Filechooser init thread finished.");
472 // Add the service change listener
473 changeSupport.addJalviewPropertyChangeListener("services",
474 new PropertyChangeListener()
478 public void propertyChange(PropertyChangeEvent evt)
480 Cache.log.debug("Firing service changed event for "
481 + evt.getNewValue());
482 JalviewServicesChanged(evt);
488 public void doConfigureStructurePrefs()
490 // configure services
491 StructureSelectionManager ssm = StructureSelectionManager
492 .getStructureSelectionManager(this);
493 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
495 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
496 Preferences.ADD_TEMPFACT_ANN, true));
497 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
498 Preferences.STRUCT_FROM_PDB, true));
499 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
500 Preferences.USE_RNAVIEW, true));
504 ssm.setAddTempFacAnnot(false);
505 ssm.setProcessSecondaryStructure(false);
506 ssm.setSecStructServices(false);
510 public void checkForNews()
512 final Desktop me = this;
513 // Thread off the news reader, in case there are connection problems.
514 addDialogThread(new Runnable()
519 Cache.log.debug("Starting news thread.");
521 jvnews = new BlogReader(me);
522 showNews.setVisible(true);
523 Cache.log.debug("Completed news thread.");
529 protected void showNews_actionPerformed(ActionEvent e)
531 showNews(showNews.isSelected());
534 void showNews(boolean visible)
537 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
538 showNews.setSelected(visible);
539 if (visible && !jvnews.isVisible())
541 new Thread(new Runnable()
546 long now = System.currentTimeMillis();
547 Desktop.instance.setProgressBar(
548 MessageManager.getString("status.refreshing_news"), now);
549 jvnews.refreshNews();
550 Desktop.instance.setProgressBar(null, now);
559 * recover the last known dimensions for a jalview window
562 * - empty string is desktop, all other windows have unique prefix
563 * @return null or last known dimensions scaled to current geometry (if last
564 * window geom was known)
566 Rectangle getLastKnownDimensions(String windowName)
568 // TODO: lock aspect ratio for scaling desktop Bug #0058199
569 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
570 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
571 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
572 String width = jalview.bin.Cache.getProperty(windowName
574 String height = jalview.bin.Cache.getProperty(windowName
576 if ((x != null) && (y != null) && (width != null) && (height != null))
578 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
579 .parseInt(width), ih = Integer.parseInt(height);
580 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
582 // attempt #1 - try to cope with change in screen geometry - this
583 // version doesn't preserve original jv aspect ratio.
584 // take ratio of current screen size vs original screen size.
585 double sw = ((1f * screenSize.width) / (1f * Integer
586 .parseInt(jalview.bin.Cache
587 .getProperty("SCREENGEOMETRY_WIDTH"))));
588 double sh = ((1f * screenSize.height) / (1f * Integer
589 .parseInt(jalview.bin.Cache
590 .getProperty("SCREENGEOMETRY_HEIGHT"))));
591 // rescale the bounds depending upon the current screen geometry.
592 ix = (int) (ix * sw);
593 iw = (int) (iw * sw);
594 iy = (int) (iy * sh);
595 ih = (int) (ih * sh);
596 while (ix >= screenSize.width)
598 jalview.bin.Cache.log
599 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
600 ix -= screenSize.width;
602 while (iy >= screenSize.height)
604 jalview.bin.Cache.log
605 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
606 iy -= screenSize.height;
608 jalview.bin.Cache.log.debug("Got last known dimensions for "
609 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
612 // return dimensions for new instance
613 return new Rectangle(ix, iy, iw, ih);
618 private void doVamsasClientCheck()
620 if (jalview.bin.Cache.vamsasJarsPresent())
622 setupVamsasDisconnectedGui();
623 VamsasMenu.setVisible(true);
624 final Desktop us = this;
625 VamsasMenu.addMenuListener(new MenuListener()
627 // this listener remembers when the menu was first selected, and
628 // doesn't rebuild the session list until it has been cleared and
630 boolean refresh = true;
633 public void menuCanceled(MenuEvent e)
639 public void menuDeselected(MenuEvent e)
645 public void menuSelected(MenuEvent e)
649 us.buildVamsasStMenu();
654 vamsasStart.setVisible(true);
658 void showPasteMenu(int x, int y)
660 JPopupMenu popup = new JPopupMenu();
661 JMenuItem item = new JMenuItem(
662 MessageManager.getString("label.paste_new_window"));
663 item.addActionListener(new ActionListener()
666 public void actionPerformed(ActionEvent evt)
673 popup.show(this, x, y);
680 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
681 Transferable contents = c.getContents(this);
683 if (contents != null)
685 String file = (String) contents
686 .getTransferData(DataFlavor.stringFlavor);
688 FileFormatI format = new IdentifyFile().identify(file,
689 DataSourceType.PASTE);
691 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
694 } catch (Exception ex)
697 .println("Unable to paste alignment from system clipboard:\n"
703 * Adds and opens the given frame to the desktop
714 public static synchronized void addInternalFrame(
715 final JInternalFrame frame, String title, int w, int h)
717 addInternalFrame(frame, title, true, w, h, true);
721 * Add an internal frame to the Jalview desktop
728 * When true, display frame immediately, otherwise, caller must call
729 * setVisible themselves.
735 public static synchronized void addInternalFrame(
736 final JInternalFrame frame, String title, boolean makeVisible,
739 addInternalFrame(frame, title, makeVisible, w, h, true);
743 * Add an internal frame to the Jalview desktop and make it visible
756 public static synchronized void addInternalFrame(
757 final JInternalFrame frame, String title, int w, int h,
760 addInternalFrame(frame, title, true, w, h, resizable);
764 * Add an internal frame to the Jalview desktop
771 * When true, display frame immediately, otherwise, caller must call
772 * setVisible themselves.
780 public static synchronized void addInternalFrame(
781 final JInternalFrame frame, String title, boolean makeVisible,
782 int w, int h, boolean resizable)
785 // TODO: allow callers to determine X and Y position of frame (eg. via
787 // TODO: consider fixing method to update entries in the window submenu with
788 // the current window title
790 frame.setTitle(title);
791 if (frame.getWidth() < 1 || frame.getHeight() < 1)
795 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
796 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
797 // IF JALVIEW IS RUNNING HEADLESS
798 // ///////////////////////////////////////////////
800 || (System.getProperty("java.awt.headless") != null && System
801 .getProperty("java.awt.headless").equals("true")))
808 frame.setVisible(makeVisible);
809 frame.setClosable(true);
810 frame.setResizable(resizable);
811 frame.setMaximizable(resizable);
812 frame.setIconifiable(resizable);
813 if (Platform.isAMac())
815 frame.setIconifiable(false);
816 frame.setFrameIcon(null);
817 // frame.setDesktopIcon(null);
818 frame.setDoubleBuffered(false);
820 if (frame.getX() < 1 && frame.getY() < 1)
822 frame.setLocation(xOffset * openFrameCount, yOffset
823 * ((openFrameCount - 1) % 10) + yOffset);
827 * add an entry for the new frame in the Window menu
828 * (and remove it when the frame is closed)
830 final JMenuItem menuItem = new JMenuItem(title);
831 frame.addInternalFrameListener(new InternalFrameAdapter()
834 public void internalFrameActivated(InternalFrameEvent evt)
836 JInternalFrame itf = desktop.getSelectedFrame();
844 public void internalFrameClosed(InternalFrameEvent evt)
846 PaintRefresher.RemoveComponent(frame);
849 * defensive check to prevent frames being
850 * added half off the window
852 if (openFrameCount > 0)
858 * ensure no reference to alignFrame retained by menu item listener
860 if (menuItem.getActionListeners().length > 0)
862 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
864 windowMenu.remove(menuItem);
865 JInternalFrame itf = desktop.getSelectedFrame();
869 if (itf instanceof AlignFrame)
871 Jalview.setCurrentAlignFrame((AlignFrame) itf);
878 menuItem.addActionListener(new ActionListener()
881 public void actionPerformed(ActionEvent e)
885 frame.setSelected(true);
886 frame.setIcon(false);
887 } catch (java.beans.PropertyVetoException ex)
896 windowMenu.add(menuItem);
901 frame.setSelected(true);
902 frame.requestFocus();
903 } catch (java.beans.PropertyVetoException ve)
905 } catch (java.lang.ClassCastException cex)
908 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
914 public void lostOwnership(Clipboard clipboard, Transferable contents)
918 Desktop.jalviewClipboard = null;
921 internalCopy = false;
925 public void dragEnter(DropTargetDragEvent evt)
930 public void dragExit(DropTargetEvent evt)
935 public void dragOver(DropTargetDragEvent evt)
940 public void dropActionChanged(DropTargetDragEvent evt)
951 public void drop(DropTargetDropEvent evt)
953 boolean success = true;
954 // JAL-1552 - acceptDrop required before getTransferable call for
955 // Java's Transferable for native dnd
956 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
957 Transferable t = evt.getTransferable();
958 List<String> files = new ArrayList<String>();
959 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
963 Desktop.transferFromDropTarget(files, protocols, evt, t);
964 } catch (Exception e)
974 for (int i = 0; i < files.size(); i++)
976 String file = files.get(i).toString();
977 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
979 FileFormatI format = null;
981 if (file.endsWith(".jar"))
983 format = FileFormat.Jalview;
988 format = new IdentifyFile().identify(file, protocol);
991 new FileLoader().LoadFile(file, protocol, format);
994 } catch (Exception ex)
999 evt.dropComplete(success); // need this to ensure input focus is properly
1000 // transfered to any new windows created
1010 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1012 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1013 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1014 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1016 chooser.setFileView(new JalviewFileView());
1017 chooser.setDialogTitle(MessageManager
1018 .getString("label.open_local_file"));
1019 chooser.setToolTipText(MessageManager.getString("action.open"));
1021 int value = chooser.showOpenDialog(this);
1023 if (value == JalviewFileChooser.APPROVE_OPTION)
1025 String choice = chooser.getSelectedFile().getPath();
1026 Cache.setProperty("LAST_DIRECTORY", chooser
1027 .getSelectedFile().getParent());
1029 FileFormatI format = chooser.getSelectedFormat();
1032 * Call IdentifyFile to verify the file contains what its extension implies.
1033 * Skip this step for dynamically added file formats, because
1034 * IdentifyFile does not know how to recognise them.
1036 boolean dynamicFormat = FileFormats.getInstance().isDynamic(format);
1037 if (!dynamicFormat && !FileFormat.Jalview.equals(format))
1041 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1042 } catch (FileFormatException e)
1048 if (viewport != null)
1050 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1055 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1067 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1069 // This construct allows us to have a wider textfield
1071 JLabel label = new JLabel(
1072 MessageManager.getString("label.input_file_url"));
1073 final JComboBox history = new JComboBox();
1075 JPanel panel = new JPanel(new GridLayout(2, 1));
1078 history.setPreferredSize(new Dimension(400, 20));
1079 history.setEditable(true);
1080 history.addItem("http://www.");
1082 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1086 if (historyItems != null)
1088 st = new StringTokenizer(historyItems, "\t");
1090 while (st.hasMoreTokens())
1092 history.addItem(st.nextElement());
1096 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1097 MessageManager.getString("label.input_alignment_from_url"),
1098 JvOptionPane.OK_CANCEL_OPTION);
1100 if (reply != JvOptionPane.OK_OPTION)
1105 String url = history.getSelectedItem().toString();
1107 if (url.toLowerCase().endsWith(".jar"))
1109 if (viewport != null)
1111 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1112 FileFormat.Jalview);
1116 new FileLoader().LoadFile(url, DataSourceType.URL,
1117 FileFormat.Jalview);
1122 FileFormatI format = null;
1125 format = new IdentifyFile().identify(url, DataSourceType.URL);
1126 } catch (FileFormatException e)
1128 // TODO revise error handling, distinguish between
1129 // URL not found and response not valid
1134 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1135 MessageManager.formatMessage("label.couldnt_locate",
1136 new Object[] { url }), MessageManager
1137 .getString("label.url_not_found"),
1138 JvOptionPane.WARNING_MESSAGE);
1143 if (viewport != null)
1146 .LoadFile(viewport, url, DataSourceType.URL, format);
1150 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1156 * Opens the CutAndPaste window for the user to paste an alignment in to
1159 * - if not null, the pasted alignment is added to the current
1160 * alignment; if null, to a new alignment window
1163 public void inputTextboxMenuItem_actionPerformed(
1164 AlignmentViewPanel viewPanel)
1166 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1167 cap.setForInput(viewPanel);
1168 Desktop.addInternalFrame(cap,
1169 MessageManager.getString("label.cut_paste_alignmen_file"),
1179 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1181 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1182 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1184 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1185 getBounds().y, getWidth(), getHeight()));
1187 if (jconsole != null)
1189 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1190 jconsole.stopConsole();
1194 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1197 if (dialogExecutor != null)
1199 dialogExecutor.shutdownNow();
1201 closeAll_actionPerformed(null);
1203 if (groovyConsole != null)
1205 // suppress a possible repeat prompt to save script
1206 groovyConsole.setDirty(false);
1207 groovyConsole.exit();
1212 private void storeLastKnownDimensions(String string, Rectangle jc)
1214 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1215 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1216 + " height:" + jc.height);
1218 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1219 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1220 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1221 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1231 public void aboutMenuItem_actionPerformed(ActionEvent e)
1233 // StringBuffer message = getAboutMessage(false);
1234 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1236 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1237 new Thread(new Runnable()
1242 new SplashScreen(true);
1247 public StringBuffer getAboutMessage(boolean shortv)
1249 StringBuffer message = new StringBuffer();
1250 message.append("<html>");
1253 message.append("<h1><strong>Version: "
1254 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1255 message.append("<strong>Last Updated: <em>"
1256 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1257 + "</em></strong>");
1263 message.append("<strong>Version "
1264 + jalview.bin.Cache.getProperty("VERSION")
1265 + "; last updated: "
1266 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1269 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1272 message.append("<br>...Checking latest version...</br>");
1274 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1275 .equals(jalview.bin.Cache.getProperty("VERSION")))
1277 boolean red = false;
1278 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1279 .indexOf("automated build") == -1)
1282 // Displayed when code version and jnlp version do not match and code
1283 // version is not a development build
1284 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1287 message.append("<br>!! Version "
1288 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1290 + " is available for download from "
1291 + jalview.bin.Cache.getDefault("www.jalview.org",
1292 "http://www.jalview.org") + " !!");
1295 message.append("</div>");
1298 message.append("<br>Authors: "
1300 .getDefault("AUTHORFNAMES",
1301 "The Jalview Authors (See AUTHORS file for current list)")
1302 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1303 + "<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"
1304 + "<br><br>If you use Jalview, please cite:"
1305 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1306 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1307 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1319 public void documentationMenuItem_actionPerformed(ActionEvent e)
1323 Help.showHelpWindow();
1324 } catch (Exception ex)
1330 public void closeAll_actionPerformed(ActionEvent e)
1332 // TODO show a progress bar while closing?
1333 JInternalFrame[] frames = desktop.getAllFrames();
1334 for (int i = 0; i < frames.length; i++)
1338 frames[i].setClosed(true);
1339 } catch (java.beans.PropertyVetoException ex)
1343 Jalview.setCurrentAlignFrame(null);
1344 System.out.println("ALL CLOSED");
1345 if (v_client != null)
1347 // TODO clear binding to vamsas document objects on close_all
1351 * reset state of singleton objects as appropriate (clear down session state
1352 * when all windows are closed)
1354 StructureSelectionManager ssm = StructureSelectionManager
1355 .getStructureSelectionManager(this);
1364 public void raiseRelated_actionPerformed(ActionEvent e)
1366 reorderAssociatedWindows(false, false);
1370 public void minimizeAssociated_actionPerformed(ActionEvent e)
1372 reorderAssociatedWindows(true, false);
1375 void closeAssociatedWindows()
1377 reorderAssociatedWindows(false, true);
1383 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1387 protected void garbageCollect_actionPerformed(ActionEvent e)
1389 // We simply collect the garbage
1390 jalview.bin.Cache.log.debug("Collecting garbage...");
1392 jalview.bin.Cache.log.debug("Finished garbage collection.");
1399 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1403 protected void showMemusage_actionPerformed(ActionEvent e)
1405 desktop.showMemoryUsage(showMemusage.isSelected());
1412 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1416 protected void showConsole_actionPerformed(ActionEvent e)
1418 showConsole(showConsole.isSelected());
1421 Console jconsole = null;
1424 * control whether the java console is visible or not
1428 void showConsole(boolean selected)
1430 showConsole.setSelected(selected);
1431 // TODO: decide if we should update properties file
1432 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1434 jconsole.setVisible(selected);
1437 void reorderAssociatedWindows(boolean minimize, boolean close)
1439 JInternalFrame[] frames = desktop.getAllFrames();
1440 if (frames == null || frames.length < 1)
1445 AlignmentViewport source = null, target = null;
1446 if (frames[0] instanceof AlignFrame)
1448 source = ((AlignFrame) frames[0]).getCurrentView();
1450 else if (frames[0] instanceof TreePanel)
1452 source = ((TreePanel) frames[0]).getViewPort();
1454 else if (frames[0] instanceof PCAPanel)
1456 source = ((PCAPanel) frames[0]).av;
1458 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1460 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1465 for (int i = 0; i < frames.length; i++)
1468 if (frames[i] == null)
1472 if (frames[i] instanceof AlignFrame)
1474 target = ((AlignFrame) frames[i]).getCurrentView();
1476 else if (frames[i] instanceof TreePanel)
1478 target = ((TreePanel) frames[i]).getViewPort();
1480 else if (frames[i] instanceof PCAPanel)
1482 target = ((PCAPanel) frames[i]).av;
1484 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1486 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1489 if (source == target)
1495 frames[i].setClosed(true);
1499 frames[i].setIcon(minimize);
1502 frames[i].toFront();
1506 } catch (java.beans.PropertyVetoException ex)
1521 protected void preferences_actionPerformed(ActionEvent e)
1533 public void saveState_actionPerformed(ActionEvent e)
1535 JalviewFileChooser chooser = new JalviewFileChooser(
1536 Cache.getProperty("LAST_DIRECTORY"), "jvp", "Jalview Project");
1538 chooser.setFileView(new JalviewFileView());
1539 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1541 int value = chooser.showSaveDialog(this);
1543 if (value == JalviewFileChooser.APPROVE_OPTION)
1545 final Desktop me = this;
1546 final java.io.File choice = chooser.getSelectedFile();
1547 setProjectFile(choice);
1549 new Thread(new Runnable()
1554 // TODO: refactor to Jalview desktop session controller action.
1555 setProgressBar(MessageManager.formatMessage(
1556 "label.saving_jalview_project",
1557 new Object[] { choice.getName() }), choice.hashCode());
1558 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1559 choice.getParent());
1560 // TODO catch and handle errors for savestate
1561 // TODO prevent user from messing with the Desktop whilst we're saving
1564 new Jalview2XML().saveState(choice);
1565 } catch (OutOfMemoryError oom)
1567 new OOMWarning("Whilst saving current state to "
1568 + choice.getName(), oom);
1569 } catch (Exception ex)
1572 "Problems whilst trying to save to " + choice.getName(),
1574 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1575 "label.error_whilst_saving_current_state_to",
1576 new Object[] { choice.getName() }), MessageManager
1577 .getString("label.couldnt_save_project"),
1578 JvOptionPane.WARNING_MESSAGE);
1580 setProgressBar(null, choice.hashCode());
1586 private void setProjectFile(File choice)
1588 this.projectFile = choice;
1591 public File getProjectFile()
1593 return this.projectFile;
1603 public void loadState_actionPerformed(ActionEvent e)
1605 JalviewFileChooser chooser = new JalviewFileChooser(
1606 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1607 "jvp", "jar" }, new String[] { "Jalview Project",
1608 "Jalview Project (old)" }, "Jalview Project");
1609 chooser.setFileView(new JalviewFileView());
1610 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1612 int value = chooser.showOpenDialog(this);
1614 if (value == JalviewFileChooser.APPROVE_OPTION)
1616 final File selectedFile = chooser.getSelectedFile();
1617 setProjectFile(selectedFile);
1618 final String choice = selectedFile.getAbsolutePath();
1619 Cache.setProperty("LAST_DIRECTORY",
1620 selectedFile.getParent());
1621 new Thread(new Runnable()
1627 MessageManager.formatMessage(
1628 "label.loading_jalview_project",
1629 new Object[] { choice }), choice.hashCode());
1632 new Jalview2XML().loadJalviewAlign(choice);
1633 } catch (OutOfMemoryError oom)
1635 new OOMWarning("Whilst loading project from " + choice, oom);
1636 } catch (Exception ex)
1638 Cache.log.error("Problems whilst loading project from "
1640 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1642 "label.error_whilst_loading_project_from",
1643 new Object[] { choice }), MessageManager
1644 .getString("label.couldnt_load_project"),
1645 JvOptionPane.WARNING_MESSAGE);
1647 setProgressBar(null, choice.hashCode());
1654 public void inputSequence_actionPerformed(ActionEvent e)
1656 new SequenceFetcher(this);
1659 JPanel progressPanel;
1661 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1663 public void startLoading(final String fileName)
1665 if (fileLoadingCount == 0)
1667 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1668 "label.loading_file", new Object[] { fileName })));
1673 private JPanel addProgressPanel(String string)
1675 if (progressPanel == null)
1677 progressPanel = new JPanel(new GridLayout(1, 1));
1678 totalProgressCount = 0;
1679 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1681 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1682 JProgressBar progressBar = new JProgressBar();
1683 progressBar.setIndeterminate(true);
1685 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1687 thisprogress.add(progressBar, BorderLayout.CENTER);
1688 progressPanel.add(thisprogress);
1689 ((GridLayout) progressPanel.getLayout())
1690 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1691 ++totalProgressCount;
1692 instance.validate();
1693 return thisprogress;
1696 int totalProgressCount = 0;
1698 private void removeProgressPanel(JPanel progbar)
1700 if (progressPanel != null)
1702 synchronized (progressPanel)
1704 progressPanel.remove(progbar);
1705 GridLayout gl = (GridLayout) progressPanel.getLayout();
1706 gl.setRows(gl.getRows() - 1);
1707 if (--totalProgressCount < 1)
1709 this.getContentPane().remove(progressPanel);
1710 progressPanel = null;
1717 public void stopLoading()
1720 if (fileLoadingCount < 1)
1722 while (fileLoadingPanels.size() > 0)
1724 removeProgressPanel(fileLoadingPanels.remove(0));
1726 fileLoadingPanels.clear();
1727 fileLoadingCount = 0;
1732 public static int getViewCount(String alignmentId)
1734 AlignmentViewport[] aps = getViewports(alignmentId);
1735 return (aps == null) ? 0 : aps.length;
1740 * @param alignmentId
1741 * - if null, all sets are returned
1742 * @return all AlignmentPanels concerning the alignmentId sequence set
1744 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1746 if (Desktop.desktop == null)
1748 // no frames created and in headless mode
1749 // TODO: verify that frames are recoverable when in headless mode
1752 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1753 AlignFrame[] frames = getAlignFrames();
1758 for (AlignFrame af : frames)
1760 for (AlignmentPanel ap : af.alignPanels)
1762 if (alignmentId == null
1763 || alignmentId.equals(ap.av.getSequenceSetId()))
1769 if (aps.size() == 0)
1773 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1778 * get all the viewports on an alignment.
1780 * @param sequenceSetId
1781 * unique alignment id (may be null - all viewports returned in that
1783 * @return all viewports on the alignment bound to sequenceSetId
1785 public static AlignmentViewport[] getViewports(String sequenceSetId)
1787 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1788 if (desktop != null)
1790 AlignFrame[] frames = Desktop.getAlignFrames();
1792 for (AlignFrame afr : frames)
1794 if (sequenceSetId == null
1795 || afr.getViewport().getSequenceSetId()
1796 .equals(sequenceSetId))
1798 if (afr.alignPanels != null)
1800 for (AlignmentPanel ap : afr.alignPanels)
1802 if (sequenceSetId == null
1803 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1811 viewp.add(afr.getViewport());
1815 if (viewp.size() > 0)
1817 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1824 * Explode the views in the given frame into separate AlignFrame
1828 public static void explodeViews(AlignFrame af)
1830 int size = af.alignPanels.size();
1836 for (int i = 0; i < size; i++)
1838 AlignmentPanel ap = af.alignPanels.get(i);
1839 AlignFrame newaf = new AlignFrame(ap);
1842 * Restore the view's last exploded frame geometry if known. Multiple
1843 * views from one exploded frame share and restore the same (frame)
1844 * position and size.
1846 Rectangle geometry = ap.av.getExplodedGeometry();
1847 if (geometry != null)
1849 newaf.setBounds(geometry);
1852 ap.av.setGatherViewsHere(false);
1854 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1855 AlignFrame.DEFAULT_HEIGHT);
1858 af.alignPanels.clear();
1859 af.closeMenuItem_actionPerformed(true);
1864 * Gather expanded views (separate AlignFrame's) with the same sequence set
1865 * identifier back in to this frame as additional views, and close the
1866 * expanded views. Note the expanded frames may themselves have multiple
1867 * views. We take the lot.
1871 public void gatherViews(AlignFrame source)
1873 source.viewport.setGatherViewsHere(true);
1874 source.viewport.setExplodedGeometry(source.getBounds());
1875 JInternalFrame[] frames = desktop.getAllFrames();
1876 String viewId = source.viewport.getSequenceSetId();
1878 for (int t = 0; t < frames.length; t++)
1880 if (frames[t] instanceof AlignFrame && frames[t] != source)
1882 AlignFrame af = (AlignFrame) frames[t];
1883 boolean gatherThis = false;
1884 for (int a = 0; a < af.alignPanels.size(); a++)
1886 AlignmentPanel ap = af.alignPanels.get(a);
1887 if (viewId.equals(ap.av.getSequenceSetId()))
1890 ap.av.setGatherViewsHere(false);
1891 ap.av.setExplodedGeometry(af.getBounds());
1892 source.addAlignmentPanel(ap, false);
1898 af.alignPanels.clear();
1899 af.closeMenuItem_actionPerformed(true);
1906 jalview.gui.VamsasApplication v_client = null;
1909 public void vamsasImport_actionPerformed(ActionEvent e)
1911 if (v_client == null)
1913 // Load and try to start a session.
1914 JalviewFileChooser chooser = new JalviewFileChooser(
1915 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1917 chooser.setFileView(new JalviewFileView());
1918 chooser.setDialogTitle(MessageManager
1919 .getString("label.open_saved_vamsas_session"));
1920 chooser.setToolTipText(MessageManager
1921 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1923 int value = chooser.showOpenDialog(this);
1925 if (value == JalviewFileChooser.APPROVE_OPTION)
1927 String fle = chooser.getSelectedFile().toString();
1928 if (!vamsasImport(chooser.getSelectedFile()))
1931 .showInternalMessageDialog(
1933 MessageManager.formatMessage(
1934 "label.couldnt_import_as_vamsas_session",
1935 new Object[] { fle }),
1937 .getString("label.vamsas_document_import_failed"),
1938 JvOptionPane.ERROR_MESSAGE);
1944 jalview.bin.Cache.log
1945 .error("Implementation error - load session from a running session is not supported.");
1950 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1953 * @return true if import was a success and a session was started.
1955 public boolean vamsasImport(URL url)
1957 // TODO: create progress bar
1958 if (v_client != null)
1961 jalview.bin.Cache.log
1962 .error("Implementation error - load session from a running session is not supported.");
1968 // copy the URL content to a temporary local file
1969 // TODO: be a bit cleverer here with nio (?!)
1970 File file = File.createTempFile("vdocfromurl", ".vdj");
1971 FileOutputStream fos = new FileOutputStream(file);
1972 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1973 byte[] buffer = new byte[2048];
1975 while ((ln = bis.read(buffer)) > -1)
1977 fos.write(buffer, 0, ln);
1981 v_client = new jalview.gui.VamsasApplication(this, file,
1982 url.toExternalForm());
1983 } catch (Exception ex)
1985 jalview.bin.Cache.log.error(
1986 "Failed to create new vamsas session from contents of URL "
1990 setupVamsasConnectedGui();
1991 v_client.initial_update(); // TODO: thread ?
1992 return v_client.inSession();
1996 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1999 * @return true if import was a success and a session was started.
2001 public boolean vamsasImport(File file)
2003 if (v_client != null)
2006 jalview.bin.Cache.log
2007 .error("Implementation error - load session from a running session is not supported.");
2011 setProgressBar(MessageManager.formatMessage(
2012 "status.importing_vamsas_session_from",
2013 new Object[] { file.getName() }), file.hashCode());
2016 v_client = new jalview.gui.VamsasApplication(this, file, null);
2017 } catch (Exception ex)
2019 setProgressBar(MessageManager.formatMessage(
2020 "status.importing_vamsas_session_from",
2021 new Object[] { file.getName() }), file.hashCode());
2022 jalview.bin.Cache.log.error(
2023 "New vamsas session from existing session file failed:", ex);
2026 setupVamsasConnectedGui();
2027 v_client.initial_update(); // TODO: thread ?
2028 setProgressBar(MessageManager.formatMessage(
2029 "status.importing_vamsas_session_from",
2030 new Object[] { file.getName() }), file.hashCode());
2031 return v_client.inSession();
2034 public boolean joinVamsasSession(String mysesid)
2036 if (v_client != null)
2040 .getString("error.try_join_vamsas_session_another"));
2042 if (mysesid == null)
2045 MessageManager.getString("error.invalid_vamsas_session_id"));
2047 v_client = new VamsasApplication(this, mysesid);
2048 setupVamsasConnectedGui();
2049 v_client.initial_update();
2050 return (v_client.inSession());
2054 public void vamsasStart_actionPerformed(ActionEvent e)
2056 if (v_client == null)
2059 // we just start a default session for moment.
2061 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2062 * getProperty("LAST_DIRECTORY"));
2064 * chooser.setFileView(new JalviewFileView());
2065 * chooser.setDialogTitle("Load Vamsas file");
2066 * chooser.setToolTipText("Import");
2068 * int value = chooser.showOpenDialog(this);
2070 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2071 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2073 v_client = new VamsasApplication(this);
2074 setupVamsasConnectedGui();
2075 v_client.initial_update(); // TODO: thread ?
2079 // store current data in session.
2080 v_client.push_update(); // TODO: thread
2084 protected void setupVamsasConnectedGui()
2086 vamsasStart.setText(MessageManager.getString("label.session_update"));
2087 vamsasSave.setVisible(true);
2088 vamsasStop.setVisible(true);
2089 vamsasImport.setVisible(false); // Document import to existing session is
2090 // not possible for vamsas-client-1.0.
2093 protected void setupVamsasDisconnectedGui()
2095 vamsasSave.setVisible(false);
2096 vamsasStop.setVisible(false);
2097 vamsasImport.setVisible(true);
2098 vamsasStart.setText(MessageManager
2099 .getString("label.new_vamsas_session"));
2103 public void vamsasStop_actionPerformed(ActionEvent e)
2105 if (v_client != null)
2107 v_client.end_session();
2109 setupVamsasDisconnectedGui();
2113 protected void buildVamsasStMenu()
2115 if (v_client == null)
2117 String[] sess = null;
2120 sess = VamsasApplication.getSessionList();
2121 } catch (Exception e)
2123 jalview.bin.Cache.log.warn(
2124 "Problem getting current sessions list.", e);
2129 jalview.bin.Cache.log.debug("Got current sessions list: "
2130 + sess.length + " entries.");
2131 VamsasStMenu.removeAll();
2132 for (int i = 0; i < sess.length; i++)
2134 JMenuItem sessit = new JMenuItem();
2135 sessit.setText(sess[i]);
2136 sessit.setToolTipText(MessageManager.formatMessage(
2137 "label.connect_to_session", new Object[] { sess[i] }));
2138 final Desktop dsktp = this;
2139 final String mysesid = sess[i];
2140 sessit.addActionListener(new ActionListener()
2144 public void actionPerformed(ActionEvent e)
2146 if (dsktp.v_client == null)
2148 Thread rthr = new Thread(new Runnable()
2154 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2155 dsktp.setupVamsasConnectedGui();
2156 dsktp.v_client.initial_update();
2164 VamsasStMenu.add(sessit);
2166 // don't show an empty menu.
2167 VamsasStMenu.setVisible(sess.length > 0);
2172 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2173 VamsasStMenu.removeAll();
2174 VamsasStMenu.setVisible(false);
2179 // Not interested in the content. Just hide ourselves.
2180 VamsasStMenu.setVisible(false);
2185 public void vamsasSave_actionPerformed(ActionEvent e)
2187 if (v_client != null)
2189 JalviewFileChooser chooser = new JalviewFileChooser(
2190 Cache.getProperty("LAST_DIRECTORY"), "vdj",// TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2193 chooser.setFileView(new JalviewFileView());
2194 chooser.setDialogTitle(MessageManager
2195 .getString("label.save_vamsas_document_archive"));
2197 int value = chooser.showSaveDialog(this);
2199 if (value == JalviewFileChooser.APPROVE_OPTION)
2201 java.io.File choice = chooser.getSelectedFile();
2202 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2203 "label.saving_vamsas_doc",
2204 new Object[] { choice.getName() }));
2205 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2206 String warnmsg = null;
2207 String warnttl = null;
2210 v_client.vclient.storeDocument(choice);
2213 warnttl = "Serious Problem saving Vamsas Document";
2214 warnmsg = ex.toString();
2215 jalview.bin.Cache.log.error("Error Whilst saving document to "
2218 } catch (Exception ex)
2220 warnttl = "Problem saving Vamsas Document.";
2221 warnmsg = ex.toString();
2222 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2226 removeProgressPanel(progpanel);
2227 if (warnmsg != null)
2229 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2231 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2237 JPanel vamUpdate = null;
2240 * hide vamsas user gui bits when a vamsas document event is being handled.
2243 * true to hide gui, false to reveal gui
2245 public void setVamsasUpdate(boolean b)
2247 Cache.log.debug("Setting gui for Vamsas update "
2248 + (b ? "in progress" : "finished"));
2250 if (vamUpdate != null)
2252 this.removeProgressPanel(vamUpdate);
2256 vamUpdate = this.addProgressPanel(MessageManager
2257 .getString("label.updating_vamsas_session"));
2259 vamsasStart.setVisible(!b);
2260 vamsasStop.setVisible(!b);
2261 vamsasSave.setVisible(!b);
2264 public JInternalFrame[] getAllFrames()
2266 return desktop.getAllFrames();
2270 * Checks the given url to see if it gives a response indicating that the user
2271 * should be informed of a new questionnaire.
2275 public void checkForQuestionnaire(String url)
2277 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2278 // javax.swing.SwingUtilities.invokeLater(jvq);
2279 new Thread(jvq).start();
2282 public void checkURLLinks()
2284 // Thread off the URL link checker
2285 addDialogThread(new Runnable()
2290 if (Cache.getDefault("CHECKURLLINKS", true))
2292 // check what the actual links are - if it's just the default don't
2293 // bother with the warning
2294 Vector<String> links = Preferences.sequenceURLLinks;
2296 // only need to check links if there is one with a
2297 // SEQUENCE_ID which is not the default EMBL_EBI link
2298 ListIterator<String> li = links.listIterator();
2299 boolean check = false;
2300 List<JLabel> urls = new ArrayList<JLabel>();
2301 while (li.hasNext())
2303 String link = li.next();
2304 if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
2307 int barPos = link.indexOf("|");
2308 String urlMsg = barPos == -1 ? link : link.substring(0,
2309 barPos) + ": " + link.substring(barPos + 1);
2310 urls.add(new JLabel(urlMsg));
2318 // ask user to check in case URL links use old style tokens
2319 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2320 JPanel msgPanel = new JPanel();
2321 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2322 msgPanel.add(Box.createVerticalGlue());
2323 JLabel msg = new JLabel(
2325 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2326 JLabel msg2 = new JLabel(
2328 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2330 for (JLabel url : urls)
2336 final JCheckBox jcb = new JCheckBox(
2337 MessageManager.getString("label.do_not_display_again"));
2338 jcb.addActionListener(new ActionListener()
2341 public void actionPerformed(ActionEvent e)
2343 // update Cache settings for "don't show this again"
2344 boolean showWarningAgain = !jcb.isSelected();
2345 Cache.setProperty("CHECKURLLINKS",
2346 Boolean.valueOf(showWarningAgain).toString());
2351 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2353 .getString("label.SEQUENCE_ID_no_longer_used"),
2354 JvOptionPane.WARNING_MESSAGE);
2361 * Proxy class for JDesktopPane which optionally displays the current memory
2362 * usage and highlights the desktop area with a red bar if free memory runs
2367 public class MyDesktopPane extends JDesktopPane implements Runnable
2370 private static final float ONE_MB = 1048576f;
2372 boolean showMemoryUsage = false;
2376 java.text.NumberFormat df;
2378 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2381 public MyDesktopPane(boolean showMemoryUsage)
2383 showMemoryUsage(showMemoryUsage);
2386 public void showMemoryUsage(boolean showMemory)
2388 this.showMemoryUsage = showMemory;
2391 Thread worker = new Thread(this);
2396 public boolean isShowMemoryUsage()
2398 return showMemoryUsage;
2404 df = java.text.NumberFormat.getNumberInstance();
2405 df.setMaximumFractionDigits(2);
2406 runtime = Runtime.getRuntime();
2408 while (showMemoryUsage)
2412 maxMemory = runtime.maxMemory() / ONE_MB;
2413 allocatedMemory = runtime.totalMemory() / ONE_MB;
2414 freeMemory = runtime.freeMemory() / ONE_MB;
2415 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2417 percentUsage = (totalFreeMemory / maxMemory) * 100;
2419 // if (percentUsage < 20)
2421 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2423 // instance.set.setBorder(border1);
2426 // sleep after showing usage
2428 } catch (Exception ex)
2430 ex.printStackTrace();
2436 public void paintComponent(Graphics g)
2438 if (showMemoryUsage && g != null && df != null)
2440 if (percentUsage < 20)
2442 g.setColor(Color.red);
2444 FontMetrics fm = g.getFontMetrics();
2447 g.drawString(MessageManager.formatMessage(
2448 "label.memory_stats",
2449 new Object[] { df.format(totalFreeMemory),
2450 df.format(maxMemory), df.format(percentUsage) }), 10,
2451 getHeight() - fm.getHeight());
2458 * fixes stacking order after a modal dialog to ensure windows that should be
2459 * on top actually are
2461 public void relayerWindows()
2466 protected JMenuItem groovyShell;
2469 * Accessor method to quickly get all the AlignmentFrames loaded.
2471 * @return an array of AlignFrame, or null if none found
2473 public static AlignFrame[] getAlignFrames()
2475 if (Jalview.isHeadlessMode())
2477 // Desktop.desktop is null in headless mode
2478 return new AlignFrame[] { Jalview.currentAlignFrame };
2481 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2487 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2489 for (int i = frames.length - 1; i > -1; i--)
2491 if (frames[i] instanceof AlignFrame)
2493 avp.add((AlignFrame) frames[i]);
2495 else if (frames[i] instanceof SplitFrame)
2498 * Also check for a split frame containing an AlignFrame
2500 GSplitFrame sf = (GSplitFrame) frames[i];
2501 if (sf.getTopFrame() instanceof AlignFrame)
2503 avp.add((AlignFrame) sf.getTopFrame());
2505 if (sf.getBottomFrame() instanceof AlignFrame)
2507 avp.add((AlignFrame) sf.getBottomFrame());
2511 if (avp.size() == 0)
2515 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2520 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2524 public GStructureViewer[] getJmols()
2526 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2532 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2534 for (int i = frames.length - 1; i > -1; i--)
2536 if (frames[i] instanceof AppJmol)
2538 GStructureViewer af = (GStructureViewer) frames[i];
2542 if (avp.size() == 0)
2546 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2551 * Add Groovy Support to Jalview
2553 public void groovyShell_actionPerformed()
2557 openGroovyConsole();
2558 } catch (Exception ex)
2560 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2561 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2563 MessageManager.getString("label.couldnt_create_groovy_shell"),
2564 MessageManager.getString("label.groovy_support_failed"),
2565 JvOptionPane.ERROR_MESSAGE);
2570 * Open the Groovy console
2572 void openGroovyConsole()
2574 if (groovyConsole == null)
2576 groovyConsole = new groovy.ui.Console();
2577 groovyConsole.setVariable("Jalview", this);
2578 groovyConsole.run();
2581 * We allow only one console at a time, so that AlignFrame menu option
2582 * 'Calculate | Run Groovy script' is unambiguous.
2583 * Disable 'Groovy Console', and enable 'Run script', when the console is
2584 * opened, and the reverse when it is closed
2586 Window window = (Window) groovyConsole.getFrame();
2587 window.addWindowListener(new WindowAdapter()
2590 public void windowClosed(WindowEvent e)
2593 * rebind CMD-Q from Groovy Console to Jalview Quit
2596 enableExecuteGroovy(false);
2602 * show Groovy console window (after close and reopen)
2604 ((Window) groovyConsole.getFrame()).setVisible(true);
2607 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2608 * and disable opening a second console
2610 enableExecuteGroovy(true);
2614 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2615 * binding when opened
2617 protected void addQuitHandler()
2619 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2620 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2621 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2622 getRootPane().getActionMap().put("Quit", new AbstractAction()
2625 public void actionPerformed(ActionEvent e)
2633 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2636 * true if Groovy console is open
2638 public void enableExecuteGroovy(boolean enabled)
2641 * disable opening a second Groovy console
2642 * (or re-enable when the console is closed)
2644 groovyShell.setEnabled(!enabled);
2646 AlignFrame[] alignFrames = getAlignFrames();
2647 if (alignFrames != null)
2649 for (AlignFrame af : alignFrames)
2651 af.setGroovyEnabled(enabled);
2657 * Progress bars managed by the IProgressIndicator method.
2659 private Hashtable<Long, JPanel> progressBars;
2661 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2666 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2669 public void setProgressBar(String message, long id)
2671 if (progressBars == null)
2673 progressBars = new Hashtable<Long, JPanel>();
2674 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2677 if (progressBars.get(new Long(id)) != null)
2679 JPanel panel = progressBars.remove(new Long(id));
2680 if (progressBarHandlers.contains(new Long(id)))
2682 progressBarHandlers.remove(new Long(id));
2684 removeProgressPanel(panel);
2688 progressBars.put(new Long(id), addProgressPanel(message));
2695 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2696 * jalview.gui.IProgressIndicatorHandler)
2699 public void registerHandler(final long id,
2700 final IProgressIndicatorHandler handler)
2702 if (progressBarHandlers == null
2703 || !progressBars.containsKey(new Long(id)))
2707 .getString("error.call_setprogressbar_before_registering_handler"));
2709 progressBarHandlers.put(new Long(id), handler);
2710 final JPanel progressPanel = progressBars.get(new Long(id));
2711 if (handler.canCancel())
2713 JButton cancel = new JButton(
2714 MessageManager.getString("action.cancel"));
2715 final IProgressIndicator us = this;
2716 cancel.addActionListener(new ActionListener()
2720 public void actionPerformed(ActionEvent e)
2722 handler.cancelActivity(id);
2723 us.setProgressBar(MessageManager.formatMessage(
2724 "label.cancelled_params",
2725 new Object[] { ((JLabel) progressPanel.getComponent(0))
2729 progressPanel.add(cancel, BorderLayout.EAST);
2735 * @return true if any progress bars are still active
2738 public boolean operationInProgress()
2740 if (progressBars != null && progressBars.size() > 0)
2748 * This will return the first AlignFrame holding the given viewport instance.
2749 * It will break if there are more than one AlignFrames viewing a particular
2753 * @return alignFrame for viewport
2755 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2757 if (desktop != null)
2759 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2760 for (int panel = 0; aps != null && panel < aps.length; panel++)
2762 if (aps[panel] != null && aps[panel].av == viewport)
2764 return aps[panel].alignFrame;
2771 public VamsasApplication getVamsasApplication()
2778 * flag set if jalview GUI is being operated programmatically
2780 private boolean inBatchMode = false;
2783 * check if jalview GUI is being operated programmatically
2785 * @return inBatchMode
2787 public boolean isInBatchMode()
2793 * set flag if jalview GUI is being operated programmatically
2795 * @param inBatchMode
2797 public void setInBatchMode(boolean inBatchMode)
2799 this.inBatchMode = inBatchMode;
2802 public void startServiceDiscovery()
2804 startServiceDiscovery(false);
2807 public void startServiceDiscovery(boolean blocking)
2809 boolean alive = true;
2810 Thread t0 = null, t1 = null, t2 = null;
2811 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2814 // todo: changesupport handlers need to be transferred
2815 if (discoverer == null)
2817 discoverer = new jalview.ws.jws1.Discoverer();
2818 // register PCS handler for desktop.
2819 discoverer.addPropertyChangeListener(changeSupport);
2821 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2822 // until we phase out completely
2823 (t0 = new Thread(discoverer)).start();
2826 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2828 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2830 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2832 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2838 // TODO: do rest service discovery
2847 } catch (Exception e)
2850 alive = (t1 != null && t1.isAlive())
2851 || (t2 != null && t2.isAlive())
2852 || (t3 != null && t3.isAlive())
2853 || (t0 != null && t0.isAlive());
2859 * called to check if the service discovery process completed successfully.
2863 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2865 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2867 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2868 .getErrorMessages();
2871 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2873 if (serviceChangedDialog == null)
2875 // only run if we aren't already displaying one of these.
2876 addDialogThread(serviceChangedDialog = new Runnable()
2883 * JalviewDialog jd =new JalviewDialog() {
2885 * @Override protected void cancelPressed() { // TODO
2886 * Auto-generated method stub
2888 * }@Override protected void okPressed() { // TODO
2889 * Auto-generated method stub
2891 * }@Override protected void raiseClosed() { // TODO
2892 * Auto-generated method stub
2894 * } }; jd.initDialogFrame(new
2895 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2896 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2897 * + " or mis-configured HTTP proxy settings.<br/>" +
2898 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2900 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2901 * ), true, true, "Web Service Configuration Problem", 450,
2904 * jd.waitForInput();
2910 "<html><table width=\"450\"><tr><td>"
2912 + "</td></tr></table>"
2913 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2914 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2915 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2916 + " Tools->Preferences dialog box to change them.</p></html>"),
2917 "Web Service Configuration Problem",
2918 JvOptionPane.DEFAULT_OPTION,
2919 JvOptionPane.ERROR_MESSAGE);
2920 serviceChangedDialog = null;
2929 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2936 private Runnable serviceChangedDialog = null;
2939 * start a thread to open a URL in the configured browser. Pops up a warning
2940 * dialog to the user if there is an exception when calling out to the browser
2945 public static void showUrl(final String url)
2947 showUrl(url, Desktop.instance);
2951 * Like showUrl but allows progress handler to be specified
2955 * (null) or object implementing IProgressIndicator
2957 public static void showUrl(final String url,
2958 final IProgressIndicator progress)
2960 new Thread(new Runnable()
2967 if (progress != null)
2969 progress.setProgressBar(MessageManager.formatMessage(
2970 "status.opening_params", new Object[] { url }), this
2973 jalview.util.BrowserLauncher.openURL(url);
2974 } catch (Exception ex)
2976 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2978 .getString("label.web_browser_not_found_unix"),
2979 MessageManager.getString("label.web_browser_not_found"),
2980 JvOptionPane.WARNING_MESSAGE);
2982 ex.printStackTrace();
2984 if (progress != null)
2986 progress.setProgressBar(null, this.hashCode());
2992 public static WsParamSetManager wsparamManager = null;
2994 public static ParamManager getUserParameterStore()
2996 if (wsparamManager == null)
2998 wsparamManager = new WsParamSetManager();
3000 return wsparamManager;
3004 * static hyperlink handler proxy method for use by Jalview's internal windows
3008 public static void hyperlinkUpdate(HyperlinkEvent e)
3010 if (e.getEventType() == EventType.ACTIVATED)
3015 url = e.getURL().toString();
3016 Desktop.showUrl(url);
3017 } catch (Exception x)
3021 if (Cache.log != null)
3023 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3027 System.err.println("Couldn't handle string " + url
3031 // ignore any exceptions due to dud links.
3038 * single thread that handles display of dialogs to user.
3040 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3043 * flag indicating if dialogExecutor should try to acquire a permit
3045 private volatile boolean dialogPause = true;
3050 private java.util.concurrent.Semaphore block = new Semaphore(0);
3052 private static groovy.ui.Console groovyConsole;
3055 * add another dialog thread to the queue
3059 public void addDialogThread(final Runnable prompter)
3061 dialogExecutor.submit(new Runnable()
3071 } catch (InterruptedException x)
3076 if (instance == null)
3082 SwingUtilities.invokeAndWait(prompter);
3083 } catch (Exception q)
3085 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3091 public void startDialogQueue()
3093 // set the flag so we don't pause waiting for another permit and semaphore
3094 // the current task to begin
3095 dialogPause = false;
3100 protected void snapShotWindow_actionPerformed(ActionEvent e)
3104 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3105 "View of Desktop", getWidth(), getHeight(), of = new File(
3106 "Jalview_snapshot" + System.currentTimeMillis()
3107 + ".eps"), "View of desktop", null, 0, false);
3110 paintAll(im.getGraphics());
3112 } catch (Exception q)
3114 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3118 Cache.log.info("Successfully written snapshot to file "
3119 + of.getAbsolutePath());
3123 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3124 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3125 * and location last time the view was expanded (if any). However it does not
3126 * remember the split pane divider location - this is set to match the
3127 * 'exploding' frame.
3131 public void explodeViews(SplitFrame sf)
3133 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3134 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3135 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3137 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3139 int viewCount = topPanels.size();
3146 * Processing in reverse order works, forwards order leaves the first panels
3147 * not visible. I don't know why!
3149 for (int i = viewCount - 1; i >= 0; i--)
3152 * Make new top and bottom frames. These take over the respective
3153 * AlignmentPanel objects, including their AlignmentViewports, so the
3154 * cdna/protein relationships between the viewports is carried over to the
3157 * explodedGeometry holds the (x, y) position of the previously exploded
3158 * SplitFrame, and the (width, height) of the AlignFrame component
3160 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3161 AlignFrame newTopFrame = new AlignFrame(topPanel);
3162 newTopFrame.setSize(oldTopFrame.getSize());
3163 newTopFrame.setVisible(true);
3164 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3165 .getExplodedGeometry();
3166 if (geometry != null)
3168 newTopFrame.setSize(geometry.getSize());
3171 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3172 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3173 newBottomFrame.setSize(oldBottomFrame.getSize());
3174 newBottomFrame.setVisible(true);
3175 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3176 .getExplodedGeometry();
3177 if (geometry != null)
3179 newBottomFrame.setSize(geometry.getSize());
3182 topPanel.av.setGatherViewsHere(false);
3183 bottomPanel.av.setGatherViewsHere(false);
3184 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3186 if (geometry != null)
3188 splitFrame.setLocation(geometry.getLocation());
3190 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3194 * Clear references to the panels (now relocated in the new SplitFrames)
3195 * before closing the old SplitFrame.
3198 bottomPanels.clear();
3203 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3204 * back into the given SplitFrame as additional views. Note that the gathered
3205 * frames may themselves have multiple views.
3209 public void gatherViews(GSplitFrame source)
3212 * special handling of explodedGeometry for a view within a SplitFrame: - it
3213 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3214 * height) of the AlignFrame component
3216 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3217 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3218 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3219 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3220 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3221 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3223 myTopFrame.viewport.setGatherViewsHere(true);
3224 myBottomFrame.viewport.setGatherViewsHere(true);
3225 String topViewId = myTopFrame.viewport.getSequenceSetId();
3226 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3228 JInternalFrame[] frames = desktop.getAllFrames();
3229 for (JInternalFrame frame : frames)
3231 if (frame instanceof SplitFrame && frame != source)
3233 SplitFrame sf = (SplitFrame) frame;
3234 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3235 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3236 boolean gatherThis = false;
3237 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3239 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3240 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3241 if (topViewId.equals(topPanel.av.getSequenceSetId())
3242 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3245 topPanel.av.setGatherViewsHere(false);
3246 bottomPanel.av.setGatherViewsHere(false);
3247 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3248 topFrame.getSize()));
3249 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3250 .getLocation(), bottomFrame.getSize()));
3251 myTopFrame.addAlignmentPanel(topPanel, false);
3252 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3258 topFrame.getAlignPanels().clear();
3259 bottomFrame.getAlignPanels().clear();
3266 * The dust settles...give focus to the tab we did this from.
3268 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3271 public static groovy.ui.Console getGroovyConsole()
3273 return groovyConsole;
3276 public static void transferFromDropTarget(List<String> files,
3277 List<DataSourceType> protocols, DropTargetDropEvent evt,
3282 DataFlavor uriListFlavor = new DataFlavor(
3283 "text/uri-list;class=java.lang.String");
3284 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3286 // Works on Windows and MacOSX
3287 Cache.log.debug("Drop handled as javaFileListFlavor");
3288 for (Object file : (List) t
3289 .getTransferData(DataFlavor.javaFileListFlavor))
3291 files.add(((File) file).toString());
3292 protocols.add(DataSourceType.FILE);
3297 // Unix like behaviour
3298 boolean added = false;
3300 if (t.isDataFlavorSupported(uriListFlavor))
3302 Cache.log.debug("Drop handled as uriListFlavor");
3303 // This is used by Unix drag system
3304 data = (String) t.getTransferData(uriListFlavor);
3308 // fallback to text: workaround - on OSX where there's a JVM bug
3309 Cache.log.debug("standard URIListFlavor failed. Trying text");
3310 // try text fallback
3311 data = (String) t.getTransferData(new DataFlavor(
3312 "text/plain;class=java.lang.String"));
3313 if (Cache.log.isDebugEnabled())
3315 Cache.log.debug("fallback returned " + data);
3318 while (protocols.size() < files.size())
3320 Cache.log.debug("Adding missing FILE protocol for "
3321 + files.get(protocols.size()));
3322 protocols.add(DataSourceType.FILE);
3324 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3325 data, "\r\n"); st.hasMoreTokens();)
3328 String s = st.nextToken();
3329 if (s.startsWith("#"))
3331 // the line is a comment (as per the RFC 2483)
3334 java.net.URI uri = new java.net.URI(s);
3335 if (uri.getScheme().toLowerCase().startsWith("http"))
3337 protocols.add(DataSourceType.URL);
3338 files.add(uri.toString());
3342 // otherwise preserve old behaviour: catch all for file objects
3343 java.io.File file = new java.io.File(uri);
3344 protocols.add(DataSourceType.FILE);
3345 files.add(file.toString());
3348 if (Cache.log.isDebugEnabled())
3350 if (data == null || !added)
3353 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3354 for (DataFlavor fl : t.getTransferDataFlavors())
3356 Cache.log.debug("Supported transfer dataflavor: "
3358 Object df = t.getTransferData(fl);
3361 Cache.log.debug("Retrieves: " + df);
3365 Cache.log.debug("Retrieved nothing");