2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.FocusEvent;
72 import java.awt.event.FocusListener;
73 import java.awt.event.KeyEvent;
74 import java.awt.event.MouseAdapter;
75 import java.awt.event.MouseEvent;
76 import java.awt.event.WindowAdapter;
77 import java.awt.event.WindowEvent;
78 import java.beans.PropertyChangeEvent;
79 import java.beans.PropertyChangeListener;
80 import java.io.BufferedInputStream;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Hashtable;
87 import java.util.List;
88 import java.util.ListIterator;
89 import java.util.StringTokenizer;
90 import java.util.Vector;
91 import java.util.concurrent.ExecutorService;
92 import java.util.concurrent.Executors;
93 import java.util.concurrent.Semaphore;
95 import javax.swing.AbstractAction;
96 import javax.swing.Box;
97 import javax.swing.BoxLayout;
98 import javax.swing.DefaultDesktopManager;
99 import javax.swing.DesktopManager;
100 import javax.swing.JButton;
101 import javax.swing.JCheckBox;
102 import javax.swing.JComboBox;
103 import javax.swing.JComponent;
104 import javax.swing.JDesktopPane;
105 import javax.swing.JFrame;
106 import javax.swing.JInternalFrame;
107 import javax.swing.JLabel;
108 import javax.swing.JMenuItem;
109 import javax.swing.JPanel;
110 import javax.swing.JPopupMenu;
111 import javax.swing.JProgressBar;
112 import javax.swing.KeyStroke;
113 import javax.swing.SwingUtilities;
114 import javax.swing.event.HyperlinkEvent;
115 import javax.swing.event.HyperlinkEvent.EventType;
116 import javax.swing.event.InternalFrameAdapter;
117 import javax.swing.event.InternalFrameEvent;
118 import javax.swing.event.MenuEvent;
119 import javax.swing.event.MenuListener;
126 * @version $Revision: 1.155 $
128 public class Desktop extends jalview.jbgui.GDesktop implements
129 DropTargetListener, ClipboardOwner, IProgressIndicator,
130 jalview.api.StructureSelectionManagerProvider
133 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
136 * news reader - null if it was never started.
138 private BlogReader jvnews = null;
140 private File projectFile;
144 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
146 public void addJalviewPropertyChangeListener(
147 PropertyChangeListener listener)
149 changeSupport.addJalviewPropertyChangeListener(listener);
153 * @param propertyName
155 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
156 * java.beans.PropertyChangeListener)
158 public void addJalviewPropertyChangeListener(String propertyName,
159 PropertyChangeListener listener)
161 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
165 * @param propertyName
167 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
168 * java.beans.PropertyChangeListener)
170 public void removeJalviewPropertyChangeListener(String propertyName,
171 PropertyChangeListener listener)
173 changeSupport.removeJalviewPropertyChangeListener(propertyName,
177 /** Singleton Desktop instance */
178 public static Desktop instance;
180 public static MyDesktopPane desktop;
182 static int openFrameCount = 0;
184 static final int xOffset = 30;
186 static final int yOffset = 30;
188 public static jalview.ws.jws1.Discoverer discoverer;
190 public static Object[] jalviewClipboard;
192 public static boolean internalCopy = false;
194 static int fileLoadingCount = 0;
196 class MyDesktopManager implements DesktopManager
199 private DesktopManager delegate;
201 public MyDesktopManager(DesktopManager delegate)
203 this.delegate = delegate;
207 public void activateFrame(JInternalFrame f)
211 delegate.activateFrame(f);
212 } catch (NullPointerException npe)
214 Point p = getMousePosition();
215 instance.showPasteMenu(p.x, p.y);
220 public void beginDraggingFrame(JComponent f)
222 delegate.beginDraggingFrame(f);
226 public void beginResizingFrame(JComponent f, int direction)
228 delegate.beginResizingFrame(f, direction);
232 public void closeFrame(JInternalFrame f)
234 delegate.closeFrame(f);
238 public void deactivateFrame(JInternalFrame f)
240 delegate.deactivateFrame(f);
244 public void deiconifyFrame(JInternalFrame f)
246 delegate.deiconifyFrame(f);
250 public void dragFrame(JComponent f, int newX, int newY)
256 delegate.dragFrame(f, newX, newY);
260 public void endDraggingFrame(JComponent f)
262 delegate.endDraggingFrame(f);
266 public void endResizingFrame(JComponent f)
268 delegate.endResizingFrame(f);
272 public void iconifyFrame(JInternalFrame f)
274 delegate.iconifyFrame(f);
278 public void maximizeFrame(JInternalFrame f)
280 delegate.maximizeFrame(f);
284 public void minimizeFrame(JInternalFrame f)
286 delegate.minimizeFrame(f);
290 public void openFrame(JInternalFrame f)
292 delegate.openFrame(f);
296 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
303 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
307 public void setBoundsForFrame(JComponent f, int newX, int newY,
308 int newWidth, int newHeight)
310 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
313 // All other methods, simply delegate
318 * Creates a new Desktop object.
323 * A note to implementors. It is ESSENTIAL that any activities that might
324 * block are spawned off as threads rather than waited for during this
328 doVamsasClientCheck();
330 groovyShell = new JMenuItem();
331 groovyShell.setText(MessageManager.getString("label.groovy_console"));
332 groovyShell.addActionListener(new ActionListener()
335 public void actionPerformed(ActionEvent e)
337 groovyShell_actionPerformed();
340 toolsMenu.add(groovyShell);
341 groovyShell.setVisible(true);
343 doConfigureStructurePrefs();
344 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
345 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
346 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
348 boolean showjconsole = jalview.bin.Cache.getDefault(
349 "SHOW_JAVA_CONSOLE", false);
350 desktop = new MyDesktopPane(selmemusage);
351 if (Platform.isAMac())
353 desktop.setDoubleBuffered(false);
355 showMemusage.setSelected(selmemusage);
356 desktop.setBackground(Color.white);
357 getContentPane().setLayout(new BorderLayout());
358 // alternate config - have scrollbars - see notes in JAL-153
359 // JScrollPane sp = new JScrollPane();
360 // sp.getViewport().setView(desktop);
361 // getContentPane().add(sp, BorderLayout.CENTER);
362 getContentPane().add(desktop, BorderLayout.CENTER);
363 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
365 // This line prevents Windows Look&Feel resizing all new windows to maximum
366 // if previous window was maximised
367 desktop.setDesktopManager(new MyDesktopManager(
368 new DefaultDesktopManager()));
370 Rectangle dims = getLastKnownDimensions("");
377 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
378 setBounds((screenSize.width - 900) / 2,
379 (screenSize.height - 650) / 2, 900, 650);
381 jconsole = new Console(this, showjconsole);
382 // add essential build information
383 jconsole.setHeader("Jalview Version: "
384 + jalview.bin.Cache.getProperty("VERSION") + "\n"
385 + "Jalview Installation: "
386 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
387 + "\n" + "Build Date: "
388 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
389 + "Java version: " + System.getProperty("java.version") + "\n"
390 + System.getProperty("os.arch") + " "
391 + System.getProperty("os.name") + " "
392 + System.getProperty("os.version"));
394 showConsole(showjconsole);
396 showNews.setVisible(false);
398 getIdentifiersOrgData();
402 this.addWindowListener(new WindowAdapter()
405 public void windowClosing(WindowEvent evt)
412 this.addMouseListener(ma = new MouseAdapter()
415 public void mousePressed(MouseEvent evt)
417 if (evt.isPopupTrigger()) // Mac
419 showPasteMenu(evt.getX(), evt.getY());
424 public void mouseReleased(MouseEvent evt)
426 if (evt.isPopupTrigger()) // Windows
428 showPasteMenu(evt.getX(), evt.getY());
432 desktop.addMouseListener(ma);
434 this.addFocusListener(new FocusListener()
438 public void focusLost(FocusEvent e)
440 // TODO Auto-generated method stub
445 public void focusGained(FocusEvent e)
447 Cache.log.debug("Relaying windows after focus gain");
448 // make sure that we sort windows properly after we gain focus
449 instance.relayerWindows();
452 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
453 // Spawn a thread that shows the splashscreen
454 SwingUtilities.invokeLater(new Runnable()
463 // Thread off a new instance of the file chooser - this reduces the time it
464 // takes to open it later on.
465 new Thread(new Runnable()
470 Cache.log.debug("Filechooser init thread started.");
471 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
472 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
474 Cache.log.debug("Filechooser init thread finished.");
477 // Add the service change listener
478 changeSupport.addJalviewPropertyChangeListener("services",
479 new PropertyChangeListener()
483 public void propertyChange(PropertyChangeEvent evt)
485 Cache.log.debug("Firing service changed event for "
486 + evt.getNewValue());
487 JalviewServicesChanged(evt);
493 public void doConfigureStructurePrefs()
495 // configure services
496 StructureSelectionManager ssm = StructureSelectionManager
497 .getStructureSelectionManager(this);
498 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
500 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
501 Preferences.ADD_TEMPFACT_ANN, true));
502 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
503 Preferences.STRUCT_FROM_PDB, true));
504 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
505 Preferences.USE_RNAVIEW, true));
509 ssm.setAddTempFacAnnot(false);
510 ssm.setProcessSecondaryStructure(false);
511 ssm.setSecStructServices(false);
515 public void checkForNews()
517 final Desktop me = this;
518 // Thread off the news reader, in case there are connection problems.
519 addDialogThread(new Runnable()
524 Cache.log.debug("Starting news thread.");
526 jvnews = new BlogReader(me);
527 showNews.setVisible(true);
528 Cache.log.debug("Completed news thread.");
533 public void getIdentifiersOrgData()
535 // Thread off the identifiers fetcher
536 addDialogThread(new Runnable()
541 Cache.log.debug("Downloading data from identifiers.org");
542 UrlDownloadClient client = new UrlDownloadClient();
545 client.download(IdOrgSettings.getUrl(),
546 IdOrgSettings.getDownloadLocation());
547 } catch (IOException e)
549 Cache.log.debug("Exception downloading identifiers.org data"
557 protected void showNews_actionPerformed(ActionEvent e)
559 showNews(showNews.isSelected());
562 void showNews(boolean visible)
565 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
566 showNews.setSelected(visible);
567 if (visible && !jvnews.isVisible())
569 new Thread(new Runnable()
574 long now = System.currentTimeMillis();
575 Desktop.instance.setProgressBar(
576 MessageManager.getString("status.refreshing_news"), now);
577 jvnews.refreshNews();
578 Desktop.instance.setProgressBar(null, now);
587 * recover the last known dimensions for a jalview window
590 * - empty string is desktop, all other windows have unique prefix
591 * @return null or last known dimensions scaled to current geometry (if last
592 * window geom was known)
594 Rectangle getLastKnownDimensions(String windowName)
596 // TODO: lock aspect ratio for scaling desktop Bug #0058199
597 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
598 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
599 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
600 String width = jalview.bin.Cache.getProperty(windowName
602 String height = jalview.bin.Cache.getProperty(windowName
604 if ((x != null) && (y != null) && (width != null) && (height != null))
606 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
607 .parseInt(width), ih = Integer.parseInt(height);
608 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
610 // attempt #1 - try to cope with change in screen geometry - this
611 // version doesn't preserve original jv aspect ratio.
612 // take ratio of current screen size vs original screen size.
613 double sw = ((1f * screenSize.width) / (1f * Integer
614 .parseInt(jalview.bin.Cache
615 .getProperty("SCREENGEOMETRY_WIDTH"))));
616 double sh = ((1f * screenSize.height) / (1f * Integer
617 .parseInt(jalview.bin.Cache
618 .getProperty("SCREENGEOMETRY_HEIGHT"))));
619 // rescale the bounds depending upon the current screen geometry.
620 ix = (int) (ix * sw);
621 iw = (int) (iw * sw);
622 iy = (int) (iy * sh);
623 ih = (int) (ih * sh);
624 while (ix >= screenSize.width)
626 jalview.bin.Cache.log
627 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
628 ix -= screenSize.width;
630 while (iy >= screenSize.height)
632 jalview.bin.Cache.log
633 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
634 iy -= screenSize.height;
636 jalview.bin.Cache.log.debug("Got last known dimensions for "
637 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
640 // return dimensions for new instance
641 return new Rectangle(ix, iy, iw, ih);
646 private void doVamsasClientCheck()
648 if (jalview.bin.Cache.vamsasJarsPresent())
650 setupVamsasDisconnectedGui();
651 VamsasMenu.setVisible(true);
652 final Desktop us = this;
653 VamsasMenu.addMenuListener(new MenuListener()
655 // this listener remembers when the menu was first selected, and
656 // doesn't rebuild the session list until it has been cleared and
658 boolean refresh = true;
661 public void menuCanceled(MenuEvent e)
667 public void menuDeselected(MenuEvent e)
673 public void menuSelected(MenuEvent e)
677 us.buildVamsasStMenu();
682 vamsasStart.setVisible(true);
686 void showPasteMenu(int x, int y)
688 JPopupMenu popup = new JPopupMenu();
689 JMenuItem item = new JMenuItem(
690 MessageManager.getString("label.paste_new_window"));
691 item.addActionListener(new ActionListener()
694 public void actionPerformed(ActionEvent evt)
701 popup.show(this, x, y);
708 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
709 Transferable contents = c.getContents(this);
711 if (contents != null)
713 String file = (String) contents
714 .getTransferData(DataFlavor.stringFlavor);
716 FileFormatI format = new IdentifyFile().identify(file,
717 DataSourceType.PASTE);
719 new FileLoader().LoadFile(null, file, DataSourceType.PASTE, format);
722 } catch (Exception ex)
725 .println("Unable to paste alignment from system clipboard:\n"
731 * Adds and opens the given frame to the desktop
742 public static synchronized void addInternalFrame(
743 final JInternalFrame frame, String title, int w, int h)
745 addInternalFrame(frame, title, true, w, h, true);
749 * Add an internal frame to the Jalview desktop
756 * When true, display frame immediately, otherwise, caller must call
757 * setVisible themselves.
763 public static synchronized void addInternalFrame(
764 final JInternalFrame frame, String title, boolean makeVisible,
767 addInternalFrame(frame, title, makeVisible, w, h, true);
771 * Add an internal frame to the Jalview desktop and make it visible
784 public static synchronized void addInternalFrame(
785 final JInternalFrame frame, String title, int w, int h,
788 addInternalFrame(frame, title, true, w, h, resizable);
792 * Add an internal frame to the Jalview desktop
799 * When true, display frame immediately, otherwise, caller must call
800 * setVisible themselves.
808 public static synchronized void addInternalFrame(
809 final JInternalFrame frame, String title, boolean makeVisible,
810 int w, int h, boolean resizable)
813 // TODO: allow callers to determine X and Y position of frame (eg. via
815 // TODO: consider fixing method to update entries in the window submenu with
816 // the current window title
818 frame.setTitle(title);
819 if (frame.getWidth() < 1 || frame.getHeight() < 1)
823 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
824 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
825 // IF JALVIEW IS RUNNING HEADLESS
826 // ///////////////////////////////////////////////
828 || (System.getProperty("java.awt.headless") != null && System
829 .getProperty("java.awt.headless").equals("true")))
836 frame.setVisible(makeVisible);
837 frame.setClosable(true);
838 frame.setResizable(resizable);
839 frame.setMaximizable(resizable);
840 frame.setIconifiable(resizable);
841 if (Platform.isAMac())
843 frame.setIconifiable(false);
844 frame.setFrameIcon(null);
845 // frame.setDesktopIcon(null);
846 frame.setDoubleBuffered(false);
848 if (frame.getX() < 1 && frame.getY() < 1)
850 frame.setLocation(xOffset * openFrameCount, yOffset
851 * ((openFrameCount - 1) % 10) + yOffset);
855 * add an entry for the new frame in the Window menu
856 * (and remove it when the frame is closed)
858 final JMenuItem menuItem = new JMenuItem(title);
859 frame.addInternalFrameListener(new InternalFrameAdapter()
862 public void internalFrameActivated(InternalFrameEvent evt)
864 JInternalFrame itf = desktop.getSelectedFrame();
872 public void internalFrameClosed(InternalFrameEvent evt)
874 PaintRefresher.RemoveComponent(frame);
877 * defensive check to prevent frames being
878 * added half off the window
880 if (openFrameCount > 0)
886 * ensure no reference to alignFrame retained by menu item listener
888 if (menuItem.getActionListeners().length > 0)
890 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
892 windowMenu.remove(menuItem);
893 JInternalFrame itf = desktop.getSelectedFrame();
897 if (itf instanceof AlignFrame)
899 Jalview.setCurrentAlignFrame((AlignFrame) itf);
906 menuItem.addActionListener(new ActionListener()
909 public void actionPerformed(ActionEvent e)
913 frame.setSelected(true);
914 frame.setIcon(false);
915 } catch (java.beans.PropertyVetoException ex)
924 windowMenu.add(menuItem);
929 frame.setSelected(true);
930 frame.requestFocus();
931 } catch (java.beans.PropertyVetoException ve)
933 } catch (java.lang.ClassCastException cex)
936 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
942 public void lostOwnership(Clipboard clipboard, Transferable contents)
946 Desktop.jalviewClipboard = null;
949 internalCopy = false;
953 public void dragEnter(DropTargetDragEvent evt)
958 public void dragExit(DropTargetEvent evt)
963 public void dragOver(DropTargetDragEvent evt)
968 public void dropActionChanged(DropTargetDragEvent evt)
979 public void drop(DropTargetDropEvent evt)
981 boolean success = true;
982 // JAL-1552 - acceptDrop required before getTransferable call for
983 // Java's Transferable for native dnd
984 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
985 Transferable t = evt.getTransferable();
986 List<String> files = new ArrayList<String>();
987 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
991 Desktop.transferFromDropTarget(files, protocols, evt, t);
992 } catch (Exception e)
1002 for (int i = 0; i < files.size(); i++)
1004 String file = files.get(i).toString();
1005 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1007 FileFormatI format = null;
1009 if (file.endsWith(".jar"))
1011 format = FileFormat.Jalview;
1016 format = new IdentifyFile().identify(file, protocol);
1019 new FileLoader().LoadFile(null, file, protocol, format);
1022 } catch (Exception ex)
1027 evt.dropComplete(success); // need this to ensure input focus is properly
1028 // transfered to any new windows created
1038 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1040 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1041 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1042 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1044 chooser.setFileView(new JalviewFileView());
1045 chooser.setDialogTitle(MessageManager
1046 .getString("label.open_local_file"));
1047 chooser.setToolTipText(MessageManager.getString("action.open"));
1049 int value = chooser.showOpenDialog(this);
1051 if (value == JalviewFileChooser.APPROVE_OPTION)
1053 String choice = chooser.getSelectedFile().getPath();
1054 Cache.setProperty("LAST_DIRECTORY", chooser
1055 .getSelectedFile().getParent());
1057 FileFormatI format = chooser.getSelectedFormat();
1060 * Call IdentifyFile to verify the file contains what its extension implies.
1061 * Skip this step for dynamically added file formats, because
1062 * IdentifyFile does not know how to recognise them.
1064 if (FileFormats.getInstance().isIdentifiable(format))
1068 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1069 } catch (FileFormatException e)
1071 // format = null; //??
1075 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1087 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1089 // This construct allows us to have a wider textfield
1091 JLabel label = new JLabel(
1092 MessageManager.getString("label.input_file_url"));
1093 final JComboBox history = new JComboBox();
1095 JPanel panel = new JPanel(new GridLayout(2, 1));
1098 history.setPreferredSize(new Dimension(400, 20));
1099 history.setEditable(true);
1100 history.addItem("http://www.");
1102 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1106 if (historyItems != null)
1108 st = new StringTokenizer(historyItems, "\t");
1110 while (st.hasMoreTokens())
1112 history.addItem(st.nextElement());
1116 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1117 MessageManager.getString("label.input_alignment_from_url"),
1118 JvOptionPane.OK_CANCEL_OPTION);
1120 if (reply != JvOptionPane.OK_OPTION)
1125 String url = history.getSelectedItem().toString();
1127 if (url.toLowerCase().endsWith(".jar"))
1129 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1130 FileFormat.Jalview);
1134 FileFormatI format = null;
1137 format = new IdentifyFile().identify(url, DataSourceType.URL);
1138 } catch (FileFormatException e)
1140 // TODO revise error handling, distinguish between
1141 // URL not found and response not valid
1146 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1147 MessageManager.formatMessage("label.couldnt_locate",
1148 new Object[] { url }), MessageManager
1149 .getString("label.url_not_found"),
1150 JvOptionPane.WARNING_MESSAGE);
1155 new FileLoader().LoadFile(viewport, url, DataSourceType.URL, format);
1160 * Opens the CutAndPaste window for the user to paste an alignment in to
1163 * - if not null, the pasted alignment is added to the current
1164 * alignment; if null, to a new alignment window
1167 public void inputTextboxMenuItem_actionPerformed(
1168 AlignmentViewPanel viewPanel)
1170 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1171 cap.setForInput(viewPanel);
1172 Desktop.addInternalFrame(cap,
1173 MessageManager.getString("label.cut_paste_alignmen_file"),
1183 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1185 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1186 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1188 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1189 getBounds().y, getWidth(), getHeight()));
1191 if (jconsole != null)
1193 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1194 jconsole.stopConsole();
1198 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1201 if (dialogExecutor != null)
1203 dialogExecutor.shutdownNow();
1205 closeAll_actionPerformed(null);
1207 if (groovyConsole != null)
1209 // suppress a possible repeat prompt to save script
1210 groovyConsole.setDirty(false);
1211 groovyConsole.exit();
1216 private void storeLastKnownDimensions(String string, Rectangle jc)
1218 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1219 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1220 + " height:" + jc.height);
1222 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1223 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1224 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1225 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1235 public void aboutMenuItem_actionPerformed(ActionEvent e)
1237 // StringBuffer message = getAboutMessage(false);
1238 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1240 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1241 new Thread(new Runnable()
1246 new SplashScreen(true);
1251 public StringBuffer getAboutMessage(boolean shortv)
1253 StringBuffer message = new StringBuffer();
1254 message.append("<html>");
1257 message.append("<h1><strong>Version: "
1258 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1259 message.append("<strong>Last Updated: <em>"
1260 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1261 + "</em></strong>");
1267 message.append("<strong>Version "
1268 + jalview.bin.Cache.getProperty("VERSION")
1269 + "; last updated: "
1270 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1273 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1276 message.append("<br>...Checking latest version...</br>");
1278 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1279 .equals(jalview.bin.Cache.getProperty("VERSION")))
1281 boolean red = false;
1282 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1283 .indexOf("automated build") == -1)
1286 // Displayed when code version and jnlp version do not match and code
1287 // version is not a development build
1288 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1291 message.append("<br>!! Version "
1292 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1294 + " is available for download from "
1295 + jalview.bin.Cache.getDefault("www.jalview.org",
1296 "http://www.jalview.org") + " !!");
1299 message.append("</div>");
1302 message.append("<br>Authors: "
1304 .getDefault("AUTHORFNAMES",
1305 "The Jalview Authors (See AUTHORS file for current list)")
1306 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1307 + "<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"
1308 + "<br><br>If you use Jalview, please cite:"
1309 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1310 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1311 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1323 public void documentationMenuItem_actionPerformed(ActionEvent e)
1327 Help.showHelpWindow();
1328 } catch (Exception ex)
1334 public void closeAll_actionPerformed(ActionEvent e)
1336 // TODO show a progress bar while closing?
1337 JInternalFrame[] frames = desktop.getAllFrames();
1338 for (int i = 0; i < frames.length; i++)
1342 frames[i].setClosed(true);
1343 } catch (java.beans.PropertyVetoException ex)
1347 Jalview.setCurrentAlignFrame(null);
1348 System.out.println("ALL CLOSED");
1349 if (v_client != null)
1351 // TODO clear binding to vamsas document objects on close_all
1355 * reset state of singleton objects as appropriate (clear down session state
1356 * when all windows are closed)
1358 StructureSelectionManager ssm = StructureSelectionManager
1359 .getStructureSelectionManager(this);
1368 public void raiseRelated_actionPerformed(ActionEvent e)
1370 reorderAssociatedWindows(false, false);
1374 public void minimizeAssociated_actionPerformed(ActionEvent e)
1376 reorderAssociatedWindows(true, false);
1379 void closeAssociatedWindows()
1381 reorderAssociatedWindows(false, true);
1387 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1391 protected void garbageCollect_actionPerformed(ActionEvent e)
1393 // We simply collect the garbage
1394 jalview.bin.Cache.log.debug("Collecting garbage...");
1396 jalview.bin.Cache.log.debug("Finished garbage collection.");
1403 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1407 protected void showMemusage_actionPerformed(ActionEvent e)
1409 desktop.showMemoryUsage(showMemusage.isSelected());
1416 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1420 protected void showConsole_actionPerformed(ActionEvent e)
1422 showConsole(showConsole.isSelected());
1425 Console jconsole = null;
1428 * control whether the java console is visible or not
1432 void showConsole(boolean selected)
1434 showConsole.setSelected(selected);
1435 // TODO: decide if we should update properties file
1436 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1438 jconsole.setVisible(selected);
1441 void reorderAssociatedWindows(boolean minimize, boolean close)
1443 JInternalFrame[] frames = desktop.getAllFrames();
1444 if (frames == null || frames.length < 1)
1449 AlignmentViewport source = null, target = null;
1450 if (frames[0] instanceof AlignFrame)
1452 source = ((AlignFrame) frames[0]).getCurrentView();
1454 else if (frames[0] instanceof TreePanel)
1456 source = ((TreePanel) frames[0]).getViewPort();
1458 else if (frames[0] instanceof PCAPanel)
1460 source = ((PCAPanel) frames[0]).av;
1462 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1464 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1469 for (int i = 0; i < frames.length; i++)
1472 if (frames[i] == null)
1476 if (frames[i] instanceof AlignFrame)
1478 target = ((AlignFrame) frames[i]).getCurrentView();
1480 else if (frames[i] instanceof TreePanel)
1482 target = ((TreePanel) frames[i]).getViewPort();
1484 else if (frames[i] instanceof PCAPanel)
1486 target = ((PCAPanel) frames[i]).av;
1488 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1490 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1493 if (source == target)
1499 frames[i].setClosed(true);
1503 frames[i].setIcon(minimize);
1506 frames[i].toFront();
1510 } catch (java.beans.PropertyVetoException ex)
1525 protected void preferences_actionPerformed(ActionEvent e)
1537 public void saveState_actionPerformed(ActionEvent e)
1539 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
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 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2194 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
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 List<String> links = Preferences.sequenceUrlLinks
2301 // only need to check links if there is one with a
2302 // SEQUENCE_ID which is not the default EMBL_EBI link
2303 ListIterator<String> li = links.listIterator();
2304 boolean check = false;
2305 List<JLabel> urls = new ArrayList<JLabel>();
2306 while (li.hasNext())
2308 String link = li.next();
2309 if (link.contains(SEQUENCE_ID)
2310 && !link.equals(UrlConstants.DEFAULT_STRING))
2313 int barPos = link.indexOf("|");
2314 String urlMsg = barPos == -1 ? link : link.substring(0,
2315 barPos) + ": " + link.substring(barPos + 1);
2316 urls.add(new JLabel(urlMsg));
2324 // ask user to check in case URL links use old style tokens
2325 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2326 JPanel msgPanel = new JPanel();
2327 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2328 msgPanel.add(Box.createVerticalGlue());
2329 JLabel msg = new JLabel(
2331 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2332 JLabel msg2 = new JLabel(
2334 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2336 for (JLabel url : urls)
2342 final JCheckBox jcb = new JCheckBox(
2343 MessageManager.getString("label.do_not_display_again"));
2344 jcb.addActionListener(new ActionListener()
2347 public void actionPerformed(ActionEvent e)
2349 // update Cache settings for "don't show this again"
2350 boolean showWarningAgain = !jcb.isSelected();
2351 Cache.setProperty("CHECKURLLINKS",
2352 Boolean.valueOf(showWarningAgain).toString());
2357 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2359 .getString("label.SEQUENCE_ID_no_longer_used"),
2360 JvOptionPane.WARNING_MESSAGE);
2367 * Proxy class for JDesktopPane which optionally displays the current memory
2368 * usage and highlights the desktop area with a red bar if free memory runs
2373 public class MyDesktopPane extends JDesktopPane implements Runnable
2376 private static final float ONE_MB = 1048576f;
2378 boolean showMemoryUsage = false;
2382 java.text.NumberFormat df;
2384 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2387 public MyDesktopPane(boolean showMemoryUsage)
2389 showMemoryUsage(showMemoryUsage);
2392 public void showMemoryUsage(boolean showMemory)
2394 this.showMemoryUsage = showMemory;
2397 Thread worker = new Thread(this);
2402 public boolean isShowMemoryUsage()
2404 return showMemoryUsage;
2410 df = java.text.NumberFormat.getNumberInstance();
2411 df.setMaximumFractionDigits(2);
2412 runtime = Runtime.getRuntime();
2414 while (showMemoryUsage)
2418 maxMemory = runtime.maxMemory() / ONE_MB;
2419 allocatedMemory = runtime.totalMemory() / ONE_MB;
2420 freeMemory = runtime.freeMemory() / ONE_MB;
2421 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2423 percentUsage = (totalFreeMemory / maxMemory) * 100;
2425 // if (percentUsage < 20)
2427 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2429 // instance.set.setBorder(border1);
2432 // sleep after showing usage
2434 } catch (Exception ex)
2436 ex.printStackTrace();
2442 public void paintComponent(Graphics g)
2444 if (showMemoryUsage && g != null && df != null)
2446 if (percentUsage < 20)
2448 g.setColor(Color.red);
2450 FontMetrics fm = g.getFontMetrics();
2453 g.drawString(MessageManager.formatMessage(
2454 "label.memory_stats",
2455 new Object[] { df.format(totalFreeMemory),
2456 df.format(maxMemory), df.format(percentUsage) }), 10,
2457 getHeight() - fm.getHeight());
2464 * fixes stacking order after a modal dialog to ensure windows that should be
2465 * on top actually are
2467 public void relayerWindows()
2472 protected JMenuItem groovyShell;
2475 * Accessor method to quickly get all the AlignmentFrames loaded.
2477 * @return an array of AlignFrame, or null if none found
2479 public static AlignFrame[] getAlignFrames()
2481 if (Jalview.isHeadlessMode())
2483 // Desktop.desktop is null in headless mode
2484 return new AlignFrame[] { Jalview.currentAlignFrame };
2487 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2493 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2495 for (int i = frames.length - 1; i > -1; i--)
2497 if (frames[i] instanceof AlignFrame)
2499 avp.add((AlignFrame) frames[i]);
2501 else if (frames[i] instanceof SplitFrame)
2504 * Also check for a split frame containing an AlignFrame
2506 GSplitFrame sf = (GSplitFrame) frames[i];
2507 if (sf.getTopFrame() instanceof AlignFrame)
2509 avp.add((AlignFrame) sf.getTopFrame());
2511 if (sf.getBottomFrame() instanceof AlignFrame)
2513 avp.add((AlignFrame) sf.getBottomFrame());
2517 if (avp.size() == 0)
2521 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2526 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2530 public GStructureViewer[] getJmols()
2532 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2538 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2540 for (int i = frames.length - 1; i > -1; i--)
2542 if (frames[i] instanceof AppJmol)
2544 GStructureViewer af = (GStructureViewer) frames[i];
2548 if (avp.size() == 0)
2552 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2557 * Add Groovy Support to Jalview
2559 public void groovyShell_actionPerformed()
2563 openGroovyConsole();
2564 } catch (Exception ex)
2566 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2567 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2569 MessageManager.getString("label.couldnt_create_groovy_shell"),
2570 MessageManager.getString("label.groovy_support_failed"),
2571 JvOptionPane.ERROR_MESSAGE);
2576 * Open the Groovy console
2578 void openGroovyConsole()
2580 if (groovyConsole == null)
2582 groovyConsole = new groovy.ui.Console();
2583 groovyConsole.setVariable("Jalview", this);
2584 groovyConsole.run();
2587 * We allow only one console at a time, so that AlignFrame menu option
2588 * 'Calculate | Run Groovy script' is unambiguous.
2589 * Disable 'Groovy Console', and enable 'Run script', when the console is
2590 * opened, and the reverse when it is closed
2592 Window window = (Window) groovyConsole.getFrame();
2593 window.addWindowListener(new WindowAdapter()
2596 public void windowClosed(WindowEvent e)
2599 * rebind CMD-Q from Groovy Console to Jalview Quit
2602 enableExecuteGroovy(false);
2608 * show Groovy console window (after close and reopen)
2610 ((Window) groovyConsole.getFrame()).setVisible(true);
2613 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2614 * and disable opening a second console
2616 enableExecuteGroovy(true);
2620 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2621 * binding when opened
2623 protected void addQuitHandler()
2625 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2626 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2627 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2628 getRootPane().getActionMap().put("Quit", new AbstractAction()
2631 public void actionPerformed(ActionEvent e)
2639 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2642 * true if Groovy console is open
2644 public void enableExecuteGroovy(boolean enabled)
2647 * disable opening a second Groovy console
2648 * (or re-enable when the console is closed)
2650 groovyShell.setEnabled(!enabled);
2652 AlignFrame[] alignFrames = getAlignFrames();
2653 if (alignFrames != null)
2655 for (AlignFrame af : alignFrames)
2657 af.setGroovyEnabled(enabled);
2663 * Progress bars managed by the IProgressIndicator method.
2665 private Hashtable<Long, JPanel> progressBars;
2667 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2672 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2675 public void setProgressBar(String message, long id)
2677 if (progressBars == null)
2679 progressBars = new Hashtable<Long, JPanel>();
2680 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2683 if (progressBars.get(new Long(id)) != null)
2685 JPanel panel = progressBars.remove(new Long(id));
2686 if (progressBarHandlers.contains(new Long(id)))
2688 progressBarHandlers.remove(new Long(id));
2690 removeProgressPanel(panel);
2694 progressBars.put(new Long(id), addProgressPanel(message));
2701 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2702 * jalview.gui.IProgressIndicatorHandler)
2705 public void registerHandler(final long id,
2706 final IProgressIndicatorHandler handler)
2708 if (progressBarHandlers == null
2709 || !progressBars.containsKey(new Long(id)))
2713 .getString("error.call_setprogressbar_before_registering_handler"));
2715 progressBarHandlers.put(new Long(id), handler);
2716 final JPanel progressPanel = progressBars.get(new Long(id));
2717 if (handler.canCancel())
2719 JButton cancel = new JButton(
2720 MessageManager.getString("action.cancel"));
2721 final IProgressIndicator us = this;
2722 cancel.addActionListener(new ActionListener()
2726 public void actionPerformed(ActionEvent e)
2728 handler.cancelActivity(id);
2729 us.setProgressBar(MessageManager.formatMessage(
2730 "label.cancelled_params",
2731 new Object[] { ((JLabel) progressPanel.getComponent(0))
2735 progressPanel.add(cancel, BorderLayout.EAST);
2741 * @return true if any progress bars are still active
2744 public boolean operationInProgress()
2746 if (progressBars != null && progressBars.size() > 0)
2754 * This will return the first AlignFrame holding the given viewport instance.
2755 * It will break if there are more than one AlignFrames viewing a particular
2759 * @return alignFrame for viewport
2761 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2763 if (desktop != null)
2765 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2766 for (int panel = 0; aps != null && panel < aps.length; panel++)
2768 if (aps[panel] != null && aps[panel].av == viewport)
2770 return aps[panel].alignFrame;
2777 public VamsasApplication getVamsasApplication()
2784 * flag set if jalview GUI is being operated programmatically
2786 private boolean inBatchMode = false;
2789 * check if jalview GUI is being operated programmatically
2791 * @return inBatchMode
2793 public boolean isInBatchMode()
2799 * set flag if jalview GUI is being operated programmatically
2801 * @param inBatchMode
2803 public void setInBatchMode(boolean inBatchMode)
2805 this.inBatchMode = inBatchMode;
2808 public void startServiceDiscovery()
2810 startServiceDiscovery(false);
2813 public void startServiceDiscovery(boolean blocking)
2815 boolean alive = true;
2816 Thread t0 = null, t1 = null, t2 = null;
2817 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2820 // todo: changesupport handlers need to be transferred
2821 if (discoverer == null)
2823 discoverer = new jalview.ws.jws1.Discoverer();
2824 // register PCS handler for desktop.
2825 discoverer.addPropertyChangeListener(changeSupport);
2827 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2828 // until we phase out completely
2829 (t0 = new Thread(discoverer)).start();
2832 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2834 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2839 // TODO: do rest service discovery
2848 } catch (Exception e)
2851 alive = (t1 != null && t1.isAlive())
2852 || (t2 != null && t2.isAlive())
2853 || (t3 != null && t3.isAlive())
2854 || (t0 != null && t0.isAlive());
2860 * called to check if the service discovery process completed successfully.
2864 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2866 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2868 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2869 .getErrorMessages();
2872 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2874 if (serviceChangedDialog == null)
2876 // only run if we aren't already displaying one of these.
2877 addDialogThread(serviceChangedDialog = new Runnable()
2884 * JalviewDialog jd =new JalviewDialog() {
2886 * @Override protected void cancelPressed() { // TODO
2887 * Auto-generated method stub
2889 * }@Override protected void okPressed() { // TODO
2890 * Auto-generated method stub
2892 * }@Override protected void raiseClosed() { // TODO
2893 * Auto-generated method stub
2895 * } }; jd.initDialogFrame(new
2896 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2897 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2898 * + " or mis-configured HTTP proxy settings.<br/>" +
2899 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2901 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2902 * ), true, true, "Web Service Configuration Problem", 450,
2905 * jd.waitForInput();
2911 "<html><table width=\"450\"><tr><td>"
2913 + "</td></tr></table>"
2914 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2915 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2916 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2917 + " Tools->Preferences dialog box to change them.</p></html>"),
2918 "Web Service Configuration Problem",
2919 JvOptionPane.DEFAULT_OPTION,
2920 JvOptionPane.ERROR_MESSAGE);
2921 serviceChangedDialog = null;
2930 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2937 private Runnable serviceChangedDialog = null;
2940 * start a thread to open a URL in the configured browser. Pops up a warning
2941 * dialog to the user if there is an exception when calling out to the browser
2946 public static void showUrl(final String url)
2948 showUrl(url, Desktop.instance);
2952 * Like showUrl but allows progress handler to be specified
2956 * (null) or object implementing IProgressIndicator
2958 public static void showUrl(final String url,
2959 final IProgressIndicator progress)
2961 new Thread(new Runnable()
2968 if (progress != null)
2970 progress.setProgressBar(MessageManager.formatMessage(
2971 "status.opening_params", new Object[] { url }), this
2974 jalview.util.BrowserLauncher.openURL(url);
2975 } catch (Exception ex)
2977 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2979 .getString("label.web_browser_not_found_unix"),
2980 MessageManager.getString("label.web_browser_not_found"),
2981 JvOptionPane.WARNING_MESSAGE);
2983 ex.printStackTrace();
2985 if (progress != null)
2987 progress.setProgressBar(null, this.hashCode());
2993 public static WsParamSetManager wsparamManager = null;
2995 public static ParamManager getUserParameterStore()
2997 if (wsparamManager == null)
2999 wsparamManager = new WsParamSetManager();
3001 return wsparamManager;
3005 * static hyperlink handler proxy method for use by Jalview's internal windows
3009 public static void hyperlinkUpdate(HyperlinkEvent e)
3011 if (e.getEventType() == EventType.ACTIVATED)
3016 url = e.getURL().toString();
3017 Desktop.showUrl(url);
3018 } catch (Exception x)
3022 if (Cache.log != null)
3024 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3028 System.err.println("Couldn't handle string " + url
3032 // ignore any exceptions due to dud links.
3039 * single thread that handles display of dialogs to user.
3041 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3044 * flag indicating if dialogExecutor should try to acquire a permit
3046 private volatile boolean dialogPause = true;
3051 private java.util.concurrent.Semaphore block = new Semaphore(0);
3053 private static groovy.ui.Console groovyConsole;
3056 * add another dialog thread to the queue
3060 public void addDialogThread(final Runnable prompter)
3062 dialogExecutor.submit(new Runnable()
3072 } catch (InterruptedException x)
3077 if (instance == null)
3083 SwingUtilities.invokeAndWait(prompter);
3084 } catch (Exception q)
3086 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3092 public void startDialogQueue()
3094 // set the flag so we don't pause waiting for another permit and semaphore
3095 // the current task to begin
3096 dialogPause = false;
3101 protected void snapShotWindow_actionPerformed(ActionEvent e)
3105 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3106 "View of Desktop", getWidth(), getHeight(), of = new File(
3107 "Jalview_snapshot" + System.currentTimeMillis()
3108 + ".eps"), "View of desktop", null, 0, false);
3111 paintAll(im.getGraphics());
3113 } catch (Exception q)
3115 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3119 Cache.log.info("Successfully written snapshot to file "
3120 + of.getAbsolutePath());
3124 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3125 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3126 * and location last time the view was expanded (if any). However it does not
3127 * remember the split pane divider location - this is set to match the
3128 * 'exploding' frame.
3132 public void explodeViews(SplitFrame sf)
3134 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3135 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3136 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3138 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3140 int viewCount = topPanels.size();
3147 * Processing in reverse order works, forwards order leaves the first panels
3148 * not visible. I don't know why!
3150 for (int i = viewCount - 1; i >= 0; i--)
3153 * Make new top and bottom frames. These take over the respective
3154 * AlignmentPanel objects, including their AlignmentViewports, so the
3155 * cdna/protein relationships between the viewports is carried over to the
3158 * explodedGeometry holds the (x, y) position of the previously exploded
3159 * SplitFrame, and the (width, height) of the AlignFrame component
3161 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3162 AlignFrame newTopFrame = new AlignFrame(topPanel);
3163 newTopFrame.setSize(oldTopFrame.getSize());
3164 newTopFrame.setVisible(true);
3165 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3166 .getExplodedGeometry();
3167 if (geometry != null)
3169 newTopFrame.setSize(geometry.getSize());
3172 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3173 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3174 newBottomFrame.setSize(oldBottomFrame.getSize());
3175 newBottomFrame.setVisible(true);
3176 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3177 .getExplodedGeometry();
3178 if (geometry != null)
3180 newBottomFrame.setSize(geometry.getSize());
3183 topPanel.av.setGatherViewsHere(false);
3184 bottomPanel.av.setGatherViewsHere(false);
3185 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3187 if (geometry != null)
3189 splitFrame.setLocation(geometry.getLocation());
3191 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3195 * Clear references to the panels (now relocated in the new SplitFrames)
3196 * before closing the old SplitFrame.
3199 bottomPanels.clear();
3204 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3205 * back into the given SplitFrame as additional views. Note that the gathered
3206 * frames may themselves have multiple views.
3210 public void gatherViews(GSplitFrame source)
3213 * special handling of explodedGeometry for a view within a SplitFrame: - it
3214 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3215 * height) of the AlignFrame component
3217 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3218 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3219 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3220 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3221 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3222 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3224 myTopFrame.viewport.setGatherViewsHere(true);
3225 myBottomFrame.viewport.setGatherViewsHere(true);
3226 String topViewId = myTopFrame.viewport.getSequenceSetId();
3227 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3229 JInternalFrame[] frames = desktop.getAllFrames();
3230 for (JInternalFrame frame : frames)
3232 if (frame instanceof SplitFrame && frame != source)
3234 SplitFrame sf = (SplitFrame) frame;
3235 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3236 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3237 boolean gatherThis = false;
3238 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3240 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3241 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3242 if (topViewId.equals(topPanel.av.getSequenceSetId())
3243 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3246 topPanel.av.setGatherViewsHere(false);
3247 bottomPanel.av.setGatherViewsHere(false);
3248 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3249 topFrame.getSize()));
3250 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3251 .getLocation(), bottomFrame.getSize()));
3252 myTopFrame.addAlignmentPanel(topPanel, false);
3253 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3259 topFrame.getAlignPanels().clear();
3260 bottomFrame.getAlignPanels().clear();
3267 * The dust settles...give focus to the tab we did this from.
3269 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3272 public static groovy.ui.Console getGroovyConsole()
3274 return groovyConsole;
3277 public static void transferFromDropTarget(List<String> files,
3278 List<DataSourceType> protocols, DropTargetDropEvent evt,
3283 DataFlavor uriListFlavor = new DataFlavor(
3284 "text/uri-list;class=java.lang.String");
3285 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3287 // Works on Windows and MacOSX
3288 Cache.log.debug("Drop handled as javaFileListFlavor");
3289 for (Object file : (List) t
3290 .getTransferData(DataFlavor.javaFileListFlavor))
3292 files.add(((File) file).toString());
3293 protocols.add(DataSourceType.FILE);
3298 // Unix like behaviour
3299 boolean added = false;
3301 if (t.isDataFlavorSupported(uriListFlavor))
3303 Cache.log.debug("Drop handled as uriListFlavor");
3304 // This is used by Unix drag system
3305 data = (String) t.getTransferData(uriListFlavor);
3309 // fallback to text: workaround - on OSX where there's a JVM bug
3310 Cache.log.debug("standard URIListFlavor failed. Trying text");
3311 // try text fallback
3312 data = (String) t.getTransferData(new DataFlavor(
3313 "text/plain;class=java.lang.String"));
3314 if (Cache.log.isDebugEnabled())
3316 Cache.log.debug("fallback returned " + data);
3319 while (protocols.size() < files.size())
3321 Cache.log.debug("Adding missing FILE protocol for "
3322 + files.get(protocols.size()));
3323 protocols.add(DataSourceType.FILE);
3325 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3326 data, "\r\n"); st.hasMoreTokens();)
3329 String s = st.nextToken();
3330 if (s.startsWith("#"))
3332 // the line is a comment (as per the RFC 2483)
3335 java.net.URI uri = new java.net.URI(s);
3336 if (uri.getScheme().toLowerCase().startsWith("http"))
3338 protocols.add(DataSourceType.URL);
3339 files.add(uri.toString());
3343 // otherwise preserve old behaviour: catch all for file objects
3344 java.io.File file = new java.io.File(uri);
3345 protocols.add(DataSourceType.FILE);
3346 files.add(file.toString());
3349 if (Cache.log.isDebugEnabled())
3351 if (data == null || !added)
3354 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3355 for (DataFlavor fl : t.getTransferDataFlavors())
3357 Cache.log.debug("Supported transfer dataflavor: "
3359 Object df = t.getTransferData(fl);
3362 Cache.log.debug("Retrieves: " + df);
3366 Cache.log.debug("Retrieved nothing");