2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.FocusEvent;
72 import java.awt.event.FocusListener;
73 import java.awt.event.KeyEvent;
74 import java.awt.event.MouseAdapter;
75 import java.awt.event.MouseEvent;
76 import java.awt.event.WindowAdapter;
77 import java.awt.event.WindowEvent;
78 import java.beans.PropertyChangeEvent;
79 import java.beans.PropertyChangeListener;
80 import java.io.BufferedInputStream;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Hashtable;
87 import java.util.List;
88 import java.util.ListIterator;
89 import java.util.StringTokenizer;
90 import java.util.Vector;
91 import java.util.concurrent.ExecutorService;
92 import java.util.concurrent.Executors;
93 import java.util.concurrent.Semaphore;
95 import javax.swing.AbstractAction;
96 import javax.swing.Box;
97 import javax.swing.BoxLayout;
98 import javax.swing.DefaultDesktopManager;
99 import javax.swing.DesktopManager;
100 import javax.swing.JButton;
101 import javax.swing.JCheckBox;
102 import javax.swing.JComboBox;
103 import javax.swing.JComponent;
104 import javax.swing.JDesktopPane;
105 import javax.swing.JFrame;
106 import javax.swing.JInternalFrame;
107 import javax.swing.JLabel;
108 import javax.swing.JMenuItem;
109 import javax.swing.JPanel;
110 import javax.swing.JPopupMenu;
111 import javax.swing.JProgressBar;
112 import javax.swing.KeyStroke;
113 import javax.swing.SwingUtilities;
114 import javax.swing.event.HyperlinkEvent;
115 import javax.swing.event.HyperlinkEvent.EventType;
116 import javax.swing.event.InternalFrameAdapter;
117 import javax.swing.event.InternalFrameEvent;
118 import javax.swing.event.MenuEvent;
119 import javax.swing.event.MenuListener;
126 * @version $Revision: 1.155 $
128 public class Desktop extends jalview.jbgui.GDesktop implements
129 DropTargetListener, ClipboardOwner, IProgressIndicator,
130 jalview.api.StructureSelectionManagerProvider
132 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
134 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
137 * news reader - null if it was never started.
139 private BlogReader jvnews = null;
141 private File projectFile;
145 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
147 public void addJalviewPropertyChangeListener(
148 PropertyChangeListener listener)
150 changeSupport.addJalviewPropertyChangeListener(listener);
154 * @param propertyName
156 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
157 * java.beans.PropertyChangeListener)
159 public void addJalviewPropertyChangeListener(String propertyName,
160 PropertyChangeListener listener)
162 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
166 * @param propertyName
168 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
169 * java.beans.PropertyChangeListener)
171 public void removeJalviewPropertyChangeListener(String propertyName,
172 PropertyChangeListener listener)
174 changeSupport.removeJalviewPropertyChangeListener(propertyName,
178 /** Singleton Desktop instance */
179 public static Desktop instance;
181 public static MyDesktopPane desktop;
183 static int openFrameCount = 0;
185 static final int xOffset = 30;
187 static final int yOffset = 30;
189 public static jalview.ws.jws1.Discoverer discoverer;
191 public static Object[] jalviewClipboard;
193 public static boolean internalCopy = false;
195 static int fileLoadingCount = 0;
197 class MyDesktopManager implements DesktopManager
200 private DesktopManager delegate;
202 public MyDesktopManager(DesktopManager delegate)
204 this.delegate = delegate;
208 public void activateFrame(JInternalFrame f)
212 delegate.activateFrame(f);
213 } catch (NullPointerException npe)
215 Point p = getMousePosition();
216 instance.showPasteMenu(p.x, p.y);
221 public void beginDraggingFrame(JComponent f)
223 delegate.beginDraggingFrame(f);
227 public void beginResizingFrame(JComponent f, int direction)
229 delegate.beginResizingFrame(f, direction);
233 public void closeFrame(JInternalFrame f)
235 delegate.closeFrame(f);
239 public void deactivateFrame(JInternalFrame f)
241 delegate.deactivateFrame(f);
245 public void deiconifyFrame(JInternalFrame f)
247 delegate.deiconifyFrame(f);
251 public void dragFrame(JComponent f, int newX, int newY)
257 delegate.dragFrame(f, newX, newY);
261 public void endDraggingFrame(JComponent f)
263 delegate.endDraggingFrame(f);
267 public void endResizingFrame(JComponent f)
269 delegate.endResizingFrame(f);
273 public void iconifyFrame(JInternalFrame f)
275 delegate.iconifyFrame(f);
279 public void maximizeFrame(JInternalFrame f)
281 delegate.maximizeFrame(f);
285 public void minimizeFrame(JInternalFrame f)
287 delegate.minimizeFrame(f);
291 public void openFrame(JInternalFrame f)
293 delegate.openFrame(f);
297 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
304 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
308 public void setBoundsForFrame(JComponent f, int newX, int newY,
309 int newWidth, int newHeight)
311 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
314 // All other methods, simply delegate
319 * Creates a new Desktop object.
324 * A note to implementors. It is ESSENTIAL that any activities that might
325 * block are spawned off as threads rather than waited for during this
329 doVamsasClientCheck();
331 doConfigureStructurePrefs();
332 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
333 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
334 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
336 boolean showjconsole = jalview.bin.Cache.getDefault(
337 "SHOW_JAVA_CONSOLE", false);
338 desktop = new MyDesktopPane(selmemusage);
339 if (Platform.isAMac())
341 desktop.setDoubleBuffered(false);
343 showMemusage.setSelected(selmemusage);
344 desktop.setBackground(Color.white);
345 getContentPane().setLayout(new BorderLayout());
346 // alternate config - have scrollbars - see notes in JAL-153
347 // JScrollPane sp = new JScrollPane();
348 // sp.getViewport().setView(desktop);
349 // getContentPane().add(sp, BorderLayout.CENTER);
350 getContentPane().add(desktop, BorderLayout.CENTER);
351 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
353 // This line prevents Windows Look&Feel resizing all new windows to maximum
354 // if previous window was maximised
355 desktop.setDesktopManager(new MyDesktopManager(
356 new DefaultDesktopManager()));
358 Rectangle dims = getLastKnownDimensions("");
365 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
366 setBounds((screenSize.width - 900) / 2,
367 (screenSize.height - 650) / 2, 900, 650);
369 jconsole = new Console(this, showjconsole);
370 // add essential build information
371 jconsole.setHeader("Jalview Version: "
372 + jalview.bin.Cache.getProperty("VERSION") + "\n"
373 + "Jalview Installation: "
374 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
375 + "\n" + "Build Date: "
376 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
377 + "Java version: " + System.getProperty("java.version") + "\n"
378 + System.getProperty("os.arch") + " "
379 + System.getProperty("os.name") + " "
380 + System.getProperty("os.version"));
382 showConsole(showjconsole);
384 showNews.setVisible(false);
386 experimentalFeatures.setSelected(showExperimental());
388 getIdentifiersOrgData();
392 this.addWindowListener(new WindowAdapter()
395 public void windowClosing(WindowEvent evt)
402 this.addMouseListener(ma = new MouseAdapter()
405 public void mousePressed(MouseEvent evt)
407 if (evt.isPopupTrigger()) // Mac
409 showPasteMenu(evt.getX(), evt.getY());
414 public void mouseReleased(MouseEvent evt)
416 if (evt.isPopupTrigger()) // Windows
418 showPasteMenu(evt.getX(), evt.getY());
422 desktop.addMouseListener(ma);
424 this.addFocusListener(new FocusListener()
428 public void focusLost(FocusEvent e)
430 // TODO Auto-generated method stub
435 public void focusGained(FocusEvent e)
437 Cache.log.debug("Relaying windows after focus gain");
438 // make sure that we sort windows properly after we gain focus
439 instance.relayerWindows();
442 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
443 // Spawn a thread that shows the splashscreen
444 SwingUtilities.invokeLater(new Runnable()
453 // Thread off a new instance of the file chooser - this reduces the time it
454 // takes to open it later on.
455 new Thread(new Runnable()
460 Cache.log.debug("Filechooser init thread started.");
461 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
462 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
464 Cache.log.debug("Filechooser init thread finished.");
467 // Add the service change listener
468 changeSupport.addJalviewPropertyChangeListener("services",
469 new PropertyChangeListener()
473 public void propertyChange(PropertyChangeEvent evt)
475 Cache.log.debug("Firing service changed event for "
476 + evt.getNewValue());
477 JalviewServicesChanged(evt);
484 * Answers true if user preferences to enable experimental features is True
489 public boolean showExperimental()
491 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
492 Boolean.FALSE.toString());
493 return Boolean.valueOf(experimental).booleanValue();
496 public void doConfigureStructurePrefs()
498 // configure services
499 StructureSelectionManager ssm = StructureSelectionManager
500 .getStructureSelectionManager(this);
501 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
503 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
504 Preferences.ADD_TEMPFACT_ANN, true));
505 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
506 Preferences.STRUCT_FROM_PDB, true));
507 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
508 Preferences.USE_RNAVIEW, true));
512 ssm.setAddTempFacAnnot(false);
513 ssm.setProcessSecondaryStructure(false);
514 ssm.setSecStructServices(false);
518 public void checkForNews()
520 final Desktop me = this;
521 // Thread off the news reader, in case there are connection problems.
522 addDialogThread(new Runnable()
527 Cache.log.debug("Starting news thread.");
529 jvnews = new BlogReader(me);
530 showNews.setVisible(true);
531 Cache.log.debug("Completed news thread.");
536 public void getIdentifiersOrgData()
538 // Thread off the identifiers fetcher
539 addDialogThread(new Runnable()
544 Cache.log.debug("Downloading data from identifiers.org");
545 UrlDownloadClient client = new UrlDownloadClient();
548 client.download(IdOrgSettings.getUrl(),
549 IdOrgSettings.getDownloadLocation());
550 } catch (IOException e)
552 Cache.log.debug("Exception downloading identifiers.org data"
560 protected void showNews_actionPerformed(ActionEvent e)
562 showNews(showNews.isSelected());
565 void showNews(boolean visible)
568 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
569 showNews.setSelected(visible);
570 if (visible && !jvnews.isVisible())
572 new Thread(new Runnable()
577 long now = System.currentTimeMillis();
578 Desktop.instance.setProgressBar(
579 MessageManager.getString("status.refreshing_news"), now);
580 jvnews.refreshNews();
581 Desktop.instance.setProgressBar(null, now);
590 * recover the last known dimensions for a jalview window
593 * - empty string is desktop, all other windows have unique prefix
594 * @return null or last known dimensions scaled to current geometry (if last
595 * window geom was known)
597 Rectangle getLastKnownDimensions(String windowName)
599 // TODO: lock aspect ratio for scaling desktop Bug #0058199
600 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
601 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
602 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
603 String width = jalview.bin.Cache.getProperty(windowName
605 String height = jalview.bin.Cache.getProperty(windowName
607 if ((x != null) && (y != null) && (width != null) && (height != null))
609 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
610 .parseInt(width), ih = Integer.parseInt(height);
611 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
613 // attempt #1 - try to cope with change in screen geometry - this
614 // version doesn't preserve original jv aspect ratio.
615 // take ratio of current screen size vs original screen size.
616 double sw = ((1f * screenSize.width) / (1f * Integer
617 .parseInt(jalview.bin.Cache
618 .getProperty("SCREENGEOMETRY_WIDTH"))));
619 double sh = ((1f * screenSize.height) / (1f * Integer
620 .parseInt(jalview.bin.Cache
621 .getProperty("SCREENGEOMETRY_HEIGHT"))));
622 // rescale the bounds depending upon the current screen geometry.
623 ix = (int) (ix * sw);
624 iw = (int) (iw * sw);
625 iy = (int) (iy * sh);
626 ih = (int) (ih * sh);
627 while (ix >= screenSize.width)
629 jalview.bin.Cache.log
630 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
631 ix -= screenSize.width;
633 while (iy >= screenSize.height)
635 jalview.bin.Cache.log
636 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
637 iy -= screenSize.height;
639 jalview.bin.Cache.log.debug("Got last known dimensions for "
640 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
643 // return dimensions for new instance
644 return new Rectangle(ix, iy, iw, ih);
649 private void doVamsasClientCheck()
651 if (jalview.bin.Cache.vamsasJarsPresent())
653 setupVamsasDisconnectedGui();
654 VamsasMenu.setVisible(true);
655 final Desktop us = this;
656 VamsasMenu.addMenuListener(new MenuListener()
658 // this listener remembers when the menu was first selected, and
659 // doesn't rebuild the session list until it has been cleared and
661 boolean refresh = true;
664 public void menuCanceled(MenuEvent e)
670 public void menuDeselected(MenuEvent e)
676 public void menuSelected(MenuEvent e)
680 us.buildVamsasStMenu();
685 vamsasStart.setVisible(true);
689 void showPasteMenu(int x, int y)
691 JPopupMenu popup = new JPopupMenu();
692 JMenuItem item = new JMenuItem(
693 MessageManager.getString("label.paste_new_window"));
694 item.addActionListener(new ActionListener()
697 public void actionPerformed(ActionEvent evt)
704 popup.show(this, x, y);
711 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
712 Transferable contents = c.getContents(this);
714 if (contents != null)
716 String file = (String) contents
717 .getTransferData(DataFlavor.stringFlavor);
719 FileFormatI format = new IdentifyFile().identify(file,
720 DataSourceType.PASTE);
722 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
725 } catch (Exception ex)
728 .println("Unable to paste alignment from system clipboard:\n"
734 * Adds and opens the given frame to the desktop
745 public static synchronized void addInternalFrame(
746 final JInternalFrame frame, String title, int w, int h)
748 addInternalFrame(frame, title, true, w, h, true);
752 * Add an internal frame to the Jalview desktop
759 * When true, display frame immediately, otherwise, caller must call
760 * setVisible themselves.
766 public static synchronized void addInternalFrame(
767 final JInternalFrame frame, String title, boolean makeVisible,
770 addInternalFrame(frame, title, makeVisible, w, h, true);
774 * Add an internal frame to the Jalview desktop and make it visible
787 public static synchronized void addInternalFrame(
788 final JInternalFrame frame, String title, int w, int h,
791 addInternalFrame(frame, title, true, w, h, resizable);
795 * Add an internal frame to the Jalview desktop
802 * When true, display frame immediately, otherwise, caller must call
803 * setVisible themselves.
811 public static synchronized void addInternalFrame(
812 final JInternalFrame frame, String title, boolean makeVisible,
813 int w, int h, boolean resizable)
816 // TODO: allow callers to determine X and Y position of frame (eg. via
818 // TODO: consider fixing method to update entries in the window submenu with
819 // the current window title
821 frame.setTitle(title);
822 if (frame.getWidth() < 1 || frame.getHeight() < 1)
826 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
827 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
828 // IF JALVIEW IS RUNNING HEADLESS
829 // ///////////////////////////////////////////////
831 || (System.getProperty("java.awt.headless") != null && System
832 .getProperty("java.awt.headless").equals("true")))
839 frame.setVisible(makeVisible);
840 frame.setClosable(true);
841 frame.setResizable(resizable);
842 frame.setMaximizable(resizable);
843 frame.setIconifiable(resizable);
844 if (Platform.isAMac())
846 frame.setIconifiable(false);
847 frame.setFrameIcon(null);
848 // frame.setDesktopIcon(null);
849 frame.setDoubleBuffered(false);
851 if (frame.getX() < 1 && frame.getY() < 1)
853 frame.setLocation(xOffset * openFrameCount, yOffset
854 * ((openFrameCount - 1) % 10) + yOffset);
858 * add an entry for the new frame in the Window menu
859 * (and remove it when the frame is closed)
861 final JMenuItem menuItem = new JMenuItem(title);
862 frame.addInternalFrameListener(new InternalFrameAdapter()
865 public void internalFrameActivated(InternalFrameEvent evt)
867 JInternalFrame itf = desktop.getSelectedFrame();
875 public void internalFrameClosed(InternalFrameEvent evt)
877 PaintRefresher.RemoveComponent(frame);
880 * defensive check to prevent frames being
881 * added half off the window
883 if (openFrameCount > 0)
889 * ensure no reference to alignFrame retained by menu item listener
891 if (menuItem.getActionListeners().length > 0)
893 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
895 windowMenu.remove(menuItem);
896 JInternalFrame itf = desktop.getSelectedFrame();
900 if (itf instanceof AlignFrame)
902 Jalview.setCurrentAlignFrame((AlignFrame) itf);
909 menuItem.addActionListener(new ActionListener()
912 public void actionPerformed(ActionEvent e)
916 frame.setSelected(true);
917 frame.setIcon(false);
918 } catch (java.beans.PropertyVetoException ex)
927 windowMenu.add(menuItem);
932 frame.setSelected(true);
933 frame.requestFocus();
934 } catch (java.beans.PropertyVetoException ve)
936 } catch (java.lang.ClassCastException cex)
939 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
945 public void lostOwnership(Clipboard clipboard, Transferable contents)
949 Desktop.jalviewClipboard = null;
952 internalCopy = false;
956 public void dragEnter(DropTargetDragEvent evt)
961 public void dragExit(DropTargetEvent evt)
966 public void dragOver(DropTargetDragEvent evt)
971 public void dropActionChanged(DropTargetDragEvent evt)
982 public void drop(DropTargetDropEvent evt)
984 boolean success = true;
985 // JAL-1552 - acceptDrop required before getTransferable call for
986 // Java's Transferable for native dnd
987 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
988 Transferable t = evt.getTransferable();
989 List<String> files = new ArrayList<String>();
990 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
994 Desktop.transferFromDropTarget(files, protocols, evt, t);
995 } catch (Exception e)
1005 for (int i = 0; i < files.size(); i++)
1007 String file = files.get(i).toString();
1008 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1010 FileFormatI format = null;
1012 if (file.endsWith(".jar"))
1014 format = FileFormat.Jalview;
1019 format = new IdentifyFile().identify(file, protocol);
1022 new FileLoader().LoadFile(file, protocol, format);
1025 } catch (Exception ex)
1030 evt.dropComplete(success); // need this to ensure input focus is properly
1031 // transfered to any new windows created
1041 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1043 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1044 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1045 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1047 chooser.setFileView(new JalviewFileView());
1048 chooser.setDialogTitle(MessageManager
1049 .getString("label.open_local_file"));
1050 chooser.setToolTipText(MessageManager.getString("action.open"));
1052 int value = chooser.showOpenDialog(this);
1054 if (value == JalviewFileChooser.APPROVE_OPTION)
1056 String choice = chooser.getSelectedFile().getPath();
1057 Cache.setProperty("LAST_DIRECTORY", chooser
1058 .getSelectedFile().getParent());
1060 FileFormatI format = chooser.getSelectedFormat();
1063 * Call IdentifyFile to verify the file contains what its extension implies.
1064 * Skip this step for dynamically added file formats, because
1065 * IdentifyFile does not know how to recognise them.
1067 if (FileFormats.getInstance().isIdentifiable(format))
1071 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1072 } catch (FileFormatException e)
1074 // format = null; //??
1078 if (viewport != null)
1080 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1085 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1097 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1099 // This construct allows us to have a wider textfield
1101 JLabel label = new JLabel(
1102 MessageManager.getString("label.input_file_url"));
1103 final JComboBox history = new JComboBox();
1105 JPanel panel = new JPanel(new GridLayout(2, 1));
1108 history.setPreferredSize(new Dimension(400, 20));
1109 history.setEditable(true);
1110 history.addItem("http://www.");
1112 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1116 if (historyItems != null)
1118 st = new StringTokenizer(historyItems, "\t");
1120 while (st.hasMoreTokens())
1122 history.addItem(st.nextElement());
1126 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1127 MessageManager.getString("label.input_alignment_from_url"),
1128 JvOptionPane.OK_CANCEL_OPTION);
1130 if (reply != JvOptionPane.OK_OPTION)
1135 String url = history.getSelectedItem().toString();
1137 if (url.toLowerCase().endsWith(".jar"))
1139 if (viewport != null)
1141 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1142 FileFormat.Jalview);
1146 new FileLoader().LoadFile(url, DataSourceType.URL,
1147 FileFormat.Jalview);
1152 FileFormatI format = null;
1155 format = new IdentifyFile().identify(url, DataSourceType.URL);
1156 } catch (FileFormatException e)
1158 // TODO revise error handling, distinguish between
1159 // URL not found and response not valid
1164 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1165 MessageManager.formatMessage("label.couldnt_locate",
1166 new Object[] { url }), MessageManager
1167 .getString("label.url_not_found"),
1168 JvOptionPane.WARNING_MESSAGE);
1173 if (viewport != null)
1176 .LoadFile(viewport, url, DataSourceType.URL, format);
1180 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1186 * Opens the CutAndPaste window for the user to paste an alignment in to
1189 * - if not null, the pasted alignment is added to the current
1190 * alignment; if null, to a new alignment window
1193 public void inputTextboxMenuItem_actionPerformed(
1194 AlignmentViewPanel viewPanel)
1196 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1197 cap.setForInput(viewPanel);
1198 Desktop.addInternalFrame(cap,
1199 MessageManager.getString("label.cut_paste_alignmen_file"),
1209 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1211 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1212 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1214 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1215 getBounds().y, getWidth(), getHeight()));
1217 if (jconsole != null)
1219 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1220 jconsole.stopConsole();
1224 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1227 if (dialogExecutor != null)
1229 dialogExecutor.shutdownNow();
1231 closeAll_actionPerformed(null);
1233 if (groovyConsole != null)
1235 // suppress a possible repeat prompt to save script
1236 groovyConsole.setDirty(false);
1237 groovyConsole.exit();
1242 private void storeLastKnownDimensions(String string, Rectangle jc)
1244 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1245 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1246 + " height:" + jc.height);
1248 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1249 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1250 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1251 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1261 public void aboutMenuItem_actionPerformed(ActionEvent e)
1263 // StringBuffer message = getAboutMessage(false);
1264 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1266 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1267 new Thread(new Runnable()
1272 new SplashScreen(true);
1277 public StringBuffer getAboutMessage(boolean shortv)
1279 StringBuffer message = new StringBuffer();
1280 message.append("<html>");
1283 message.append("<h1><strong>Version: "
1284 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1285 message.append("<strong>Last Updated: <em>"
1286 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1287 + "</em></strong>");
1293 message.append("<strong>Version "
1294 + jalview.bin.Cache.getProperty("VERSION")
1295 + "; last updated: "
1296 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1299 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1302 message.append("<br>...Checking latest version...</br>");
1304 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1305 .equals(jalview.bin.Cache.getProperty("VERSION")))
1307 boolean red = false;
1308 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1309 .indexOf("automated build") == -1)
1312 // Displayed when code version and jnlp version do not match and code
1313 // version is not a development build
1314 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1317 message.append("<br>!! Version "
1318 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1320 + " is available for download from "
1321 + jalview.bin.Cache.getDefault("www.jalview.org",
1322 "http://www.jalview.org") + " !!");
1325 message.append("</div>");
1328 message.append("<br>Authors: "
1330 .getDefault("AUTHORFNAMES",
1331 "The Jalview Authors (See AUTHORS file for current list)")
1332 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1333 + "<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"
1334 + "<br><br>If you use Jalview, please cite:"
1335 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1336 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1337 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1349 public void documentationMenuItem_actionPerformed(ActionEvent e)
1353 Help.showHelpWindow();
1354 } catch (Exception ex)
1360 public void closeAll_actionPerformed(ActionEvent e)
1362 // TODO show a progress bar while closing?
1363 JInternalFrame[] frames = desktop.getAllFrames();
1364 for (int i = 0; i < frames.length; i++)
1368 frames[i].setClosed(true);
1369 } catch (java.beans.PropertyVetoException ex)
1373 Jalview.setCurrentAlignFrame(null);
1374 System.out.println("ALL CLOSED");
1375 if (v_client != null)
1377 // TODO clear binding to vamsas document objects on close_all
1381 * reset state of singleton objects as appropriate (clear down session state
1382 * when all windows are closed)
1384 StructureSelectionManager ssm = StructureSelectionManager
1385 .getStructureSelectionManager(this);
1394 public void raiseRelated_actionPerformed(ActionEvent e)
1396 reorderAssociatedWindows(false, false);
1400 public void minimizeAssociated_actionPerformed(ActionEvent e)
1402 reorderAssociatedWindows(true, false);
1405 void closeAssociatedWindows()
1407 reorderAssociatedWindows(false, true);
1413 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1417 protected void garbageCollect_actionPerformed(ActionEvent e)
1419 // We simply collect the garbage
1420 jalview.bin.Cache.log.debug("Collecting garbage...");
1422 jalview.bin.Cache.log.debug("Finished garbage collection.");
1429 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1433 protected void showMemusage_actionPerformed(ActionEvent e)
1435 desktop.showMemoryUsage(showMemusage.isSelected());
1442 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1446 protected void showConsole_actionPerformed(ActionEvent e)
1448 showConsole(showConsole.isSelected());
1451 Console jconsole = null;
1454 * control whether the java console is visible or not
1458 void showConsole(boolean selected)
1460 showConsole.setSelected(selected);
1461 // TODO: decide if we should update properties file
1462 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1464 jconsole.setVisible(selected);
1467 void reorderAssociatedWindows(boolean minimize, boolean close)
1469 JInternalFrame[] frames = desktop.getAllFrames();
1470 if (frames == null || frames.length < 1)
1475 AlignmentViewport source = null, target = null;
1476 if (frames[0] instanceof AlignFrame)
1478 source = ((AlignFrame) frames[0]).getCurrentView();
1480 else if (frames[0] instanceof TreePanel)
1482 source = ((TreePanel) frames[0]).getViewPort();
1484 else if (frames[0] instanceof PCAPanel)
1486 source = ((PCAPanel) frames[0]).av;
1488 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1490 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1495 for (int i = 0; i < frames.length; i++)
1498 if (frames[i] == null)
1502 if (frames[i] instanceof AlignFrame)
1504 target = ((AlignFrame) frames[i]).getCurrentView();
1506 else if (frames[i] instanceof TreePanel)
1508 target = ((TreePanel) frames[i]).getViewPort();
1510 else if (frames[i] instanceof PCAPanel)
1512 target = ((PCAPanel) frames[i]).av;
1514 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1516 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1519 if (source == target)
1525 frames[i].setClosed(true);
1529 frames[i].setIcon(minimize);
1532 frames[i].toFront();
1536 } catch (java.beans.PropertyVetoException ex)
1551 protected void preferences_actionPerformed(ActionEvent e)
1563 public void saveState_actionPerformed(ActionEvent e)
1565 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1568 chooser.setFileView(new JalviewFileView());
1569 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1571 int value = chooser.showSaveDialog(this);
1573 if (value == JalviewFileChooser.APPROVE_OPTION)
1575 final Desktop me = this;
1576 final java.io.File choice = chooser.getSelectedFile();
1577 setProjectFile(choice);
1579 new Thread(new Runnable()
1584 // TODO: refactor to Jalview desktop session controller action.
1585 setProgressBar(MessageManager.formatMessage(
1586 "label.saving_jalview_project",
1587 new Object[] { choice.getName() }), choice.hashCode());
1588 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1589 choice.getParent());
1590 // TODO catch and handle errors for savestate
1591 // TODO prevent user from messing with the Desktop whilst we're saving
1594 new Jalview2XML().saveState(choice);
1595 } catch (OutOfMemoryError oom)
1597 new OOMWarning("Whilst saving current state to "
1598 + choice.getName(), oom);
1599 } catch (Exception ex)
1602 "Problems whilst trying to save to " + choice.getName(),
1604 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1605 "label.error_whilst_saving_current_state_to",
1606 new Object[] { choice.getName() }), MessageManager
1607 .getString("label.couldnt_save_project"),
1608 JvOptionPane.WARNING_MESSAGE);
1610 setProgressBar(null, choice.hashCode());
1616 private void setProjectFile(File choice)
1618 this.projectFile = choice;
1621 public File getProjectFile()
1623 return this.projectFile;
1633 public void loadState_actionPerformed(ActionEvent e)
1635 JalviewFileChooser chooser = new JalviewFileChooser(
1636 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1637 "jvp", "jar" }, new String[] { "Jalview Project",
1638 "Jalview Project (old)" }, "Jalview Project");
1639 chooser.setFileView(new JalviewFileView());
1640 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1642 int value = chooser.showOpenDialog(this);
1644 if (value == JalviewFileChooser.APPROVE_OPTION)
1646 final File selectedFile = chooser.getSelectedFile();
1647 setProjectFile(selectedFile);
1648 final String choice = selectedFile.getAbsolutePath();
1649 Cache.setProperty("LAST_DIRECTORY",
1650 selectedFile.getParent());
1651 new Thread(new Runnable()
1657 MessageManager.formatMessage(
1658 "label.loading_jalview_project",
1659 new Object[] { choice }), choice.hashCode());
1662 new Jalview2XML().loadJalviewAlign(choice);
1663 } catch (OutOfMemoryError oom)
1665 new OOMWarning("Whilst loading project from " + choice, oom);
1666 } catch (Exception ex)
1668 Cache.log.error("Problems whilst loading project from "
1670 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1672 "label.error_whilst_loading_project_from",
1673 new Object[] { choice }), MessageManager
1674 .getString("label.couldnt_load_project"),
1675 JvOptionPane.WARNING_MESSAGE);
1677 setProgressBar(null, choice.hashCode());
1684 public void inputSequence_actionPerformed(ActionEvent e)
1686 new SequenceFetcher(this);
1689 JPanel progressPanel;
1691 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1693 public void startLoading(final String fileName)
1695 if (fileLoadingCount == 0)
1697 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1698 "label.loading_file", new Object[] { fileName })));
1703 private JPanel addProgressPanel(String string)
1705 if (progressPanel == null)
1707 progressPanel = new JPanel(new GridLayout(1, 1));
1708 totalProgressCount = 0;
1709 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1711 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1712 JProgressBar progressBar = new JProgressBar();
1713 progressBar.setIndeterminate(true);
1715 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1717 thisprogress.add(progressBar, BorderLayout.CENTER);
1718 progressPanel.add(thisprogress);
1719 ((GridLayout) progressPanel.getLayout())
1720 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1721 ++totalProgressCount;
1722 instance.validate();
1723 return thisprogress;
1726 int totalProgressCount = 0;
1728 private void removeProgressPanel(JPanel progbar)
1730 if (progressPanel != null)
1732 synchronized (progressPanel)
1734 progressPanel.remove(progbar);
1735 GridLayout gl = (GridLayout) progressPanel.getLayout();
1736 gl.setRows(gl.getRows() - 1);
1737 if (--totalProgressCount < 1)
1739 this.getContentPane().remove(progressPanel);
1740 progressPanel = null;
1747 public void stopLoading()
1750 if (fileLoadingCount < 1)
1752 while (fileLoadingPanels.size() > 0)
1754 removeProgressPanel(fileLoadingPanels.remove(0));
1756 fileLoadingPanels.clear();
1757 fileLoadingCount = 0;
1762 public static int getViewCount(String alignmentId)
1764 AlignmentViewport[] aps = getViewports(alignmentId);
1765 return (aps == null) ? 0 : aps.length;
1770 * @param alignmentId
1771 * - if null, all sets are returned
1772 * @return all AlignmentPanels concerning the alignmentId sequence set
1774 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1776 if (Desktop.desktop == null)
1778 // no frames created and in headless mode
1779 // TODO: verify that frames are recoverable when in headless mode
1782 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1783 AlignFrame[] frames = getAlignFrames();
1788 for (AlignFrame af : frames)
1790 for (AlignmentPanel ap : af.alignPanels)
1792 if (alignmentId == null
1793 || alignmentId.equals(ap.av.getSequenceSetId()))
1799 if (aps.size() == 0)
1803 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1808 * get all the viewports on an alignment.
1810 * @param sequenceSetId
1811 * unique alignment id (may be null - all viewports returned in that
1813 * @return all viewports on the alignment bound to sequenceSetId
1815 public static AlignmentViewport[] getViewports(String sequenceSetId)
1817 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1818 if (desktop != null)
1820 AlignFrame[] frames = Desktop.getAlignFrames();
1822 for (AlignFrame afr : frames)
1824 if (sequenceSetId == null
1825 || afr.getViewport().getSequenceSetId()
1826 .equals(sequenceSetId))
1828 if (afr.alignPanels != null)
1830 for (AlignmentPanel ap : afr.alignPanels)
1832 if (sequenceSetId == null
1833 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1841 viewp.add(afr.getViewport());
1845 if (viewp.size() > 0)
1847 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1854 * Explode the views in the given frame into separate AlignFrame
1858 public static void explodeViews(AlignFrame af)
1860 int size = af.alignPanels.size();
1866 for (int i = 0; i < size; i++)
1868 AlignmentPanel ap = af.alignPanels.get(i);
1869 AlignFrame newaf = new AlignFrame(ap);
1872 * Restore the view's last exploded frame geometry if known. Multiple
1873 * views from one exploded frame share and restore the same (frame)
1874 * position and size.
1876 Rectangle geometry = ap.av.getExplodedGeometry();
1877 if (geometry != null)
1879 newaf.setBounds(geometry);
1882 ap.av.setGatherViewsHere(false);
1884 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1885 AlignFrame.DEFAULT_HEIGHT);
1888 af.alignPanels.clear();
1889 af.closeMenuItem_actionPerformed(true);
1894 * Gather expanded views (separate AlignFrame's) with the same sequence set
1895 * identifier back in to this frame as additional views, and close the
1896 * expanded views. Note the expanded frames may themselves have multiple
1897 * views. We take the lot.
1901 public void gatherViews(AlignFrame source)
1903 source.viewport.setGatherViewsHere(true);
1904 source.viewport.setExplodedGeometry(source.getBounds());
1905 JInternalFrame[] frames = desktop.getAllFrames();
1906 String viewId = source.viewport.getSequenceSetId();
1908 for (int t = 0; t < frames.length; t++)
1910 if (frames[t] instanceof AlignFrame && frames[t] != source)
1912 AlignFrame af = (AlignFrame) frames[t];
1913 boolean gatherThis = false;
1914 for (int a = 0; a < af.alignPanels.size(); a++)
1916 AlignmentPanel ap = af.alignPanels.get(a);
1917 if (viewId.equals(ap.av.getSequenceSetId()))
1920 ap.av.setGatherViewsHere(false);
1921 ap.av.setExplodedGeometry(af.getBounds());
1922 source.addAlignmentPanel(ap, false);
1928 af.alignPanels.clear();
1929 af.closeMenuItem_actionPerformed(true);
1936 jalview.gui.VamsasApplication v_client = null;
1939 public void vamsasImport_actionPerformed(ActionEvent e)
1941 if (v_client == null)
1943 // Load and try to start a session.
1944 JalviewFileChooser chooser = new JalviewFileChooser(
1945 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1947 chooser.setFileView(new JalviewFileView());
1948 chooser.setDialogTitle(MessageManager
1949 .getString("label.open_saved_vamsas_session"));
1950 chooser.setToolTipText(MessageManager
1951 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1953 int value = chooser.showOpenDialog(this);
1955 if (value == JalviewFileChooser.APPROVE_OPTION)
1957 String fle = chooser.getSelectedFile().toString();
1958 if (!vamsasImport(chooser.getSelectedFile()))
1961 .showInternalMessageDialog(
1963 MessageManager.formatMessage(
1964 "label.couldnt_import_as_vamsas_session",
1965 new Object[] { fle }),
1967 .getString("label.vamsas_document_import_failed"),
1968 JvOptionPane.ERROR_MESSAGE);
1974 jalview.bin.Cache.log
1975 .error("Implementation error - load session from a running session is not supported.");
1980 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1983 * @return true if import was a success and a session was started.
1985 public boolean vamsasImport(URL url)
1987 // TODO: create progress bar
1988 if (v_client != null)
1991 jalview.bin.Cache.log
1992 .error("Implementation error - load session from a running session is not supported.");
1998 // copy the URL content to a temporary local file
1999 // TODO: be a bit cleverer here with nio (?!)
2000 File file = File.createTempFile("vdocfromurl", ".vdj");
2001 FileOutputStream fos = new FileOutputStream(file);
2002 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2003 byte[] buffer = new byte[2048];
2005 while ((ln = bis.read(buffer)) > -1)
2007 fos.write(buffer, 0, ln);
2011 v_client = new jalview.gui.VamsasApplication(this, file,
2012 url.toExternalForm());
2013 } catch (Exception ex)
2015 jalview.bin.Cache.log.error(
2016 "Failed to create new vamsas session from contents of URL "
2020 setupVamsasConnectedGui();
2021 v_client.initial_update(); // TODO: thread ?
2022 return v_client.inSession();
2026 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2029 * @return true if import was a success and a session was started.
2031 public boolean vamsasImport(File file)
2033 if (v_client != null)
2036 jalview.bin.Cache.log
2037 .error("Implementation error - load session from a running session is not supported.");
2041 setProgressBar(MessageManager.formatMessage(
2042 "status.importing_vamsas_session_from",
2043 new Object[] { file.getName() }), file.hashCode());
2046 v_client = new jalview.gui.VamsasApplication(this, file, null);
2047 } catch (Exception ex)
2049 setProgressBar(MessageManager.formatMessage(
2050 "status.importing_vamsas_session_from",
2051 new Object[] { file.getName() }), file.hashCode());
2052 jalview.bin.Cache.log.error(
2053 "New vamsas session from existing session file failed:", ex);
2056 setupVamsasConnectedGui();
2057 v_client.initial_update(); // TODO: thread ?
2058 setProgressBar(MessageManager.formatMessage(
2059 "status.importing_vamsas_session_from",
2060 new Object[] { file.getName() }), file.hashCode());
2061 return v_client.inSession();
2064 public boolean joinVamsasSession(String mysesid)
2066 if (v_client != null)
2070 .getString("error.try_join_vamsas_session_another"));
2072 if (mysesid == null)
2075 MessageManager.getString("error.invalid_vamsas_session_id"));
2077 v_client = new VamsasApplication(this, mysesid);
2078 setupVamsasConnectedGui();
2079 v_client.initial_update();
2080 return (v_client.inSession());
2084 public void vamsasStart_actionPerformed(ActionEvent e)
2086 if (v_client == null)
2089 // we just start a default session for moment.
2091 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2092 * getProperty("LAST_DIRECTORY"));
2094 * chooser.setFileView(new JalviewFileView());
2095 * chooser.setDialogTitle("Load Vamsas file");
2096 * chooser.setToolTipText("Import");
2098 * int value = chooser.showOpenDialog(this);
2100 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2101 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2103 v_client = new VamsasApplication(this);
2104 setupVamsasConnectedGui();
2105 v_client.initial_update(); // TODO: thread ?
2109 // store current data in session.
2110 v_client.push_update(); // TODO: thread
2114 protected void setupVamsasConnectedGui()
2116 vamsasStart.setText(MessageManager.getString("label.session_update"));
2117 vamsasSave.setVisible(true);
2118 vamsasStop.setVisible(true);
2119 vamsasImport.setVisible(false); // Document import to existing session is
2120 // not possible for vamsas-client-1.0.
2123 protected void setupVamsasDisconnectedGui()
2125 vamsasSave.setVisible(false);
2126 vamsasStop.setVisible(false);
2127 vamsasImport.setVisible(true);
2128 vamsasStart.setText(MessageManager
2129 .getString("label.new_vamsas_session"));
2133 public void vamsasStop_actionPerformed(ActionEvent e)
2135 if (v_client != null)
2137 v_client.end_session();
2139 setupVamsasDisconnectedGui();
2143 protected void buildVamsasStMenu()
2145 if (v_client == null)
2147 String[] sess = null;
2150 sess = VamsasApplication.getSessionList();
2151 } catch (Exception e)
2153 jalview.bin.Cache.log.warn(
2154 "Problem getting current sessions list.", e);
2159 jalview.bin.Cache.log.debug("Got current sessions list: "
2160 + sess.length + " entries.");
2161 VamsasStMenu.removeAll();
2162 for (int i = 0; i < sess.length; i++)
2164 JMenuItem sessit = new JMenuItem();
2165 sessit.setText(sess[i]);
2166 sessit.setToolTipText(MessageManager.formatMessage(
2167 "label.connect_to_session", new Object[] { sess[i] }));
2168 final Desktop dsktp = this;
2169 final String mysesid = sess[i];
2170 sessit.addActionListener(new ActionListener()
2174 public void actionPerformed(ActionEvent e)
2176 if (dsktp.v_client == null)
2178 Thread rthr = new Thread(new Runnable()
2184 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2185 dsktp.setupVamsasConnectedGui();
2186 dsktp.v_client.initial_update();
2194 VamsasStMenu.add(sessit);
2196 // don't show an empty menu.
2197 VamsasStMenu.setVisible(sess.length > 0);
2202 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2203 VamsasStMenu.removeAll();
2204 VamsasStMenu.setVisible(false);
2209 // Not interested in the content. Just hide ourselves.
2210 VamsasStMenu.setVisible(false);
2215 public void vamsasSave_actionPerformed(ActionEvent e)
2217 if (v_client != null)
2219 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2220 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2223 chooser.setFileView(new JalviewFileView());
2224 chooser.setDialogTitle(MessageManager
2225 .getString("label.save_vamsas_document_archive"));
2227 int value = chooser.showSaveDialog(this);
2229 if (value == JalviewFileChooser.APPROVE_OPTION)
2231 java.io.File choice = chooser.getSelectedFile();
2232 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2233 "label.saving_vamsas_doc",
2234 new Object[] { choice.getName() }));
2235 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2236 String warnmsg = null;
2237 String warnttl = null;
2240 v_client.vclient.storeDocument(choice);
2243 warnttl = "Serious Problem saving Vamsas Document";
2244 warnmsg = ex.toString();
2245 jalview.bin.Cache.log.error("Error Whilst saving document to "
2248 } catch (Exception ex)
2250 warnttl = "Problem saving Vamsas Document.";
2251 warnmsg = ex.toString();
2252 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2256 removeProgressPanel(progpanel);
2257 if (warnmsg != null)
2259 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2261 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2267 JPanel vamUpdate = null;
2270 * hide vamsas user gui bits when a vamsas document event is being handled.
2273 * true to hide gui, false to reveal gui
2275 public void setVamsasUpdate(boolean b)
2277 Cache.log.debug("Setting gui for Vamsas update "
2278 + (b ? "in progress" : "finished"));
2280 if (vamUpdate != null)
2282 this.removeProgressPanel(vamUpdate);
2286 vamUpdate = this.addProgressPanel(MessageManager
2287 .getString("label.updating_vamsas_session"));
2289 vamsasStart.setVisible(!b);
2290 vamsasStop.setVisible(!b);
2291 vamsasSave.setVisible(!b);
2294 public JInternalFrame[] getAllFrames()
2296 return desktop.getAllFrames();
2300 * Checks the given url to see if it gives a response indicating that the user
2301 * should be informed of a new questionnaire.
2305 public void checkForQuestionnaire(String url)
2307 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2308 // javax.swing.SwingUtilities.invokeLater(jvq);
2309 new Thread(jvq).start();
2312 public void checkURLLinks()
2314 // Thread off the URL link checker
2315 addDialogThread(new Runnable()
2320 if (Cache.getDefault("CHECKURLLINKS", true))
2322 // check what the actual links are - if it's just the default don't
2323 // bother with the warning
2324 List<String> links = Preferences.sequenceUrlLinks
2327 // only need to check links if there is one with a
2328 // SEQUENCE_ID which is not the default EMBL_EBI link
2329 ListIterator<String> li = links.listIterator();
2330 boolean check = false;
2331 List<JLabel> urls = new ArrayList<JLabel>();
2332 while (li.hasNext())
2334 String link = li.next();
2335 if (link.contains(SEQUENCE_ID)
2336 && !link.equals(UrlConstants.DEFAULT_STRING))
2339 int barPos = link.indexOf("|");
2340 String urlMsg = barPos == -1 ? link : link.substring(0,
2341 barPos) + ": " + link.substring(barPos + 1);
2342 urls.add(new JLabel(urlMsg));
2350 // ask user to check in case URL links use old style tokens
2351 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2352 JPanel msgPanel = new JPanel();
2353 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2354 msgPanel.add(Box.createVerticalGlue());
2355 JLabel msg = new JLabel(
2357 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2358 JLabel msg2 = new JLabel(
2360 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2362 for (JLabel url : urls)
2368 final JCheckBox jcb = new JCheckBox(
2369 MessageManager.getString("label.do_not_display_again"));
2370 jcb.addActionListener(new ActionListener()
2373 public void actionPerformed(ActionEvent e)
2375 // update Cache settings for "don't show this again"
2376 boolean showWarningAgain = !jcb.isSelected();
2377 Cache.setProperty("CHECKURLLINKS",
2378 Boolean.valueOf(showWarningAgain).toString());
2383 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2385 .getString("label.SEQUENCE_ID_no_longer_used"),
2386 JvOptionPane.WARNING_MESSAGE);
2393 * Proxy class for JDesktopPane which optionally displays the current memory
2394 * usage and highlights the desktop area with a red bar if free memory runs
2399 public class MyDesktopPane extends JDesktopPane implements Runnable
2402 private static final float ONE_MB = 1048576f;
2404 boolean showMemoryUsage = false;
2408 java.text.NumberFormat df;
2410 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2413 public MyDesktopPane(boolean showMemoryUsage)
2415 showMemoryUsage(showMemoryUsage);
2418 public void showMemoryUsage(boolean showMemory)
2420 this.showMemoryUsage = showMemory;
2423 Thread worker = new Thread(this);
2428 public boolean isShowMemoryUsage()
2430 return showMemoryUsage;
2436 df = java.text.NumberFormat.getNumberInstance();
2437 df.setMaximumFractionDigits(2);
2438 runtime = Runtime.getRuntime();
2440 while (showMemoryUsage)
2444 maxMemory = runtime.maxMemory() / ONE_MB;
2445 allocatedMemory = runtime.totalMemory() / ONE_MB;
2446 freeMemory = runtime.freeMemory() / ONE_MB;
2447 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2449 percentUsage = (totalFreeMemory / maxMemory) * 100;
2451 // if (percentUsage < 20)
2453 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2455 // instance.set.setBorder(border1);
2458 // sleep after showing usage
2460 } catch (Exception ex)
2462 ex.printStackTrace();
2468 public void paintComponent(Graphics g)
2470 if (showMemoryUsage && g != null && df != null)
2472 if (percentUsage < 20)
2474 g.setColor(Color.red);
2476 FontMetrics fm = g.getFontMetrics();
2479 g.drawString(MessageManager.formatMessage(
2480 "label.memory_stats",
2481 new Object[] { df.format(totalFreeMemory),
2482 df.format(maxMemory), df.format(percentUsage) }), 10,
2483 getHeight() - fm.getHeight());
2490 * fixes stacking order after a modal dialog to ensure windows that should be
2491 * on top actually are
2493 public void relayerWindows()
2499 * Accessor method to quickly get all the AlignmentFrames loaded.
2501 * @return an array of AlignFrame, or null if none found
2503 public static AlignFrame[] getAlignFrames()
2505 if (Jalview.isHeadlessMode())
2507 // Desktop.desktop is null in headless mode
2508 return new AlignFrame[] { Jalview.currentAlignFrame };
2511 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2517 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2519 for (int i = frames.length - 1; i > -1; i--)
2521 if (frames[i] instanceof AlignFrame)
2523 avp.add((AlignFrame) frames[i]);
2525 else if (frames[i] instanceof SplitFrame)
2528 * Also check for a split frame containing an AlignFrame
2530 GSplitFrame sf = (GSplitFrame) frames[i];
2531 if (sf.getTopFrame() instanceof AlignFrame)
2533 avp.add((AlignFrame) sf.getTopFrame());
2535 if (sf.getBottomFrame() instanceof AlignFrame)
2537 avp.add((AlignFrame) sf.getBottomFrame());
2541 if (avp.size() == 0)
2545 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2550 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2554 public GStructureViewer[] getJmols()
2556 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2562 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2564 for (int i = frames.length - 1; i > -1; i--)
2566 if (frames[i] instanceof AppJmol)
2568 GStructureViewer af = (GStructureViewer) frames[i];
2572 if (avp.size() == 0)
2576 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2581 * Add Groovy Support to Jalview
2584 public void groovyShell_actionPerformed()
2588 openGroovyConsole();
2589 } catch (Exception ex)
2591 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2592 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2594 MessageManager.getString("label.couldnt_create_groovy_shell"),
2595 MessageManager.getString("label.groovy_support_failed"),
2596 JvOptionPane.ERROR_MESSAGE);
2601 * Open the Groovy console
2603 void openGroovyConsole()
2605 if (groovyConsole == null)
2607 groovyConsole = new groovy.ui.Console();
2608 groovyConsole.setVariable("Jalview", this);
2609 groovyConsole.run();
2612 * We allow only one console at a time, so that AlignFrame menu option
2613 * 'Calculate | Run Groovy script' is unambiguous.
2614 * Disable 'Groovy Console', and enable 'Run script', when the console is
2615 * opened, and the reverse when it is closed
2617 Window window = (Window) groovyConsole.getFrame();
2618 window.addWindowListener(new WindowAdapter()
2621 public void windowClosed(WindowEvent e)
2624 * rebind CMD-Q from Groovy Console to Jalview Quit
2627 enableExecuteGroovy(false);
2633 * show Groovy console window (after close and reopen)
2635 ((Window) groovyConsole.getFrame()).setVisible(true);
2638 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2639 * and disable opening a second console
2641 enableExecuteGroovy(true);
2645 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2646 * binding when opened
2648 protected void addQuitHandler()
2650 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2651 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2652 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2653 getRootPane().getActionMap().put("Quit", new AbstractAction()
2656 public void actionPerformed(ActionEvent e)
2664 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2667 * true if Groovy console is open
2669 public void enableExecuteGroovy(boolean enabled)
2672 * disable opening a second Groovy console
2673 * (or re-enable when the console is closed)
2675 groovyShell.setEnabled(!enabled);
2677 AlignFrame[] alignFrames = getAlignFrames();
2678 if (alignFrames != null)
2680 for (AlignFrame af : alignFrames)
2682 af.setGroovyEnabled(enabled);
2688 * Progress bars managed by the IProgressIndicator method.
2690 private Hashtable<Long, JPanel> progressBars;
2692 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2697 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2700 public void setProgressBar(String message, long id)
2702 if (progressBars == null)
2704 progressBars = new Hashtable<Long, JPanel>();
2705 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2708 if (progressBars.get(new Long(id)) != null)
2710 JPanel panel = progressBars.remove(new Long(id));
2711 if (progressBarHandlers.contains(new Long(id)))
2713 progressBarHandlers.remove(new Long(id));
2715 removeProgressPanel(panel);
2719 progressBars.put(new Long(id), addProgressPanel(message));
2726 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2727 * jalview.gui.IProgressIndicatorHandler)
2730 public void registerHandler(final long id,
2731 final IProgressIndicatorHandler handler)
2733 if (progressBarHandlers == null
2734 || !progressBars.containsKey(new Long(id)))
2738 .getString("error.call_setprogressbar_before_registering_handler"));
2740 progressBarHandlers.put(new Long(id), handler);
2741 final JPanel progressPanel = progressBars.get(new Long(id));
2742 if (handler.canCancel())
2744 JButton cancel = new JButton(
2745 MessageManager.getString("action.cancel"));
2746 final IProgressIndicator us = this;
2747 cancel.addActionListener(new ActionListener()
2751 public void actionPerformed(ActionEvent e)
2753 handler.cancelActivity(id);
2754 us.setProgressBar(MessageManager.formatMessage(
2755 "label.cancelled_params",
2756 new Object[] { ((JLabel) progressPanel.getComponent(0))
2760 progressPanel.add(cancel, BorderLayout.EAST);
2766 * @return true if any progress bars are still active
2769 public boolean operationInProgress()
2771 if (progressBars != null && progressBars.size() > 0)
2779 * This will return the first AlignFrame holding the given viewport instance.
2780 * It will break if there are more than one AlignFrames viewing a particular
2784 * @return alignFrame for viewport
2786 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2788 if (desktop != null)
2790 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2791 for (int panel = 0; aps != null && panel < aps.length; panel++)
2793 if (aps[panel] != null && aps[panel].av == viewport)
2795 return aps[panel].alignFrame;
2802 public VamsasApplication getVamsasApplication()
2809 * flag set if jalview GUI is being operated programmatically
2811 private boolean inBatchMode = false;
2814 * check if jalview GUI is being operated programmatically
2816 * @return inBatchMode
2818 public boolean isInBatchMode()
2824 * set flag if jalview GUI is being operated programmatically
2826 * @param inBatchMode
2828 public void setInBatchMode(boolean inBatchMode)
2830 this.inBatchMode = inBatchMode;
2833 public void startServiceDiscovery()
2835 startServiceDiscovery(false);
2838 public void startServiceDiscovery(boolean blocking)
2840 boolean alive = true;
2841 Thread t0 = null, t1 = null, t2 = null;
2842 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2845 // todo: changesupport handlers need to be transferred
2846 if (discoverer == null)
2848 discoverer = new jalview.ws.jws1.Discoverer();
2849 // register PCS handler for desktop.
2850 discoverer.addPropertyChangeListener(changeSupport);
2852 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2853 // until we phase out completely
2854 (t0 = new Thread(discoverer)).start();
2857 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2859 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2864 // TODO: do rest service discovery
2873 } catch (Exception e)
2876 alive = (t1 != null && t1.isAlive())
2877 || (t2 != null && t2.isAlive())
2878 || (t3 != null && t3.isAlive())
2879 || (t0 != null && t0.isAlive());
2885 * called to check if the service discovery process completed successfully.
2889 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2891 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2893 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2894 .getErrorMessages();
2897 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2899 if (serviceChangedDialog == null)
2901 // only run if we aren't already displaying one of these.
2902 addDialogThread(serviceChangedDialog = new Runnable()
2909 * JalviewDialog jd =new JalviewDialog() {
2911 * @Override protected void cancelPressed() { // TODO
2912 * Auto-generated method stub
2914 * }@Override protected void okPressed() { // TODO
2915 * Auto-generated method stub
2917 * }@Override protected void raiseClosed() { // TODO
2918 * Auto-generated method stub
2920 * } }; jd.initDialogFrame(new
2921 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2922 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2923 * + " or mis-configured HTTP proxy settings.<br/>" +
2924 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2926 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2927 * ), true, true, "Web Service Configuration Problem", 450,
2930 * jd.waitForInput();
2936 "<html><table width=\"450\"><tr><td>"
2938 + "</td></tr></table>"
2939 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2940 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2941 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2942 + " Tools->Preferences dialog box to change them.</p></html>"),
2943 "Web Service Configuration Problem",
2944 JvOptionPane.DEFAULT_OPTION,
2945 JvOptionPane.ERROR_MESSAGE);
2946 serviceChangedDialog = null;
2955 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2962 private Runnable serviceChangedDialog = null;
2965 * start a thread to open a URL in the configured browser. Pops up a warning
2966 * dialog to the user if there is an exception when calling out to the browser
2971 public static void showUrl(final String url)
2973 showUrl(url, Desktop.instance);
2977 * Like showUrl but allows progress handler to be specified
2981 * (null) or object implementing IProgressIndicator
2983 public static void showUrl(final String url,
2984 final IProgressIndicator progress)
2986 new Thread(new Runnable()
2993 if (progress != null)
2995 progress.setProgressBar(MessageManager.formatMessage(
2996 "status.opening_params", new Object[] { url }), this
2999 jalview.util.BrowserLauncher.openURL(url);
3000 } catch (Exception ex)
3002 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3004 .getString("label.web_browser_not_found_unix"),
3005 MessageManager.getString("label.web_browser_not_found"),
3006 JvOptionPane.WARNING_MESSAGE);
3008 ex.printStackTrace();
3010 if (progress != null)
3012 progress.setProgressBar(null, this.hashCode());
3018 public static WsParamSetManager wsparamManager = null;
3020 public static ParamManager getUserParameterStore()
3022 if (wsparamManager == null)
3024 wsparamManager = new WsParamSetManager();
3026 return wsparamManager;
3030 * static hyperlink handler proxy method for use by Jalview's internal windows
3034 public static void hyperlinkUpdate(HyperlinkEvent e)
3036 if (e.getEventType() == EventType.ACTIVATED)
3041 url = e.getURL().toString();
3042 Desktop.showUrl(url);
3043 } catch (Exception x)
3047 if (Cache.log != null)
3049 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3053 System.err.println("Couldn't handle string " + url
3057 // ignore any exceptions due to dud links.
3064 * single thread that handles display of dialogs to user.
3066 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3069 * flag indicating if dialogExecutor should try to acquire a permit
3071 private volatile boolean dialogPause = true;
3076 private java.util.concurrent.Semaphore block = new Semaphore(0);
3078 private static groovy.ui.Console groovyConsole;
3081 * add another dialog thread to the queue
3085 public void addDialogThread(final Runnable prompter)
3087 dialogExecutor.submit(new Runnable()
3097 } catch (InterruptedException x)
3102 if (instance == null)
3108 SwingUtilities.invokeAndWait(prompter);
3109 } catch (Exception q)
3111 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3117 public void startDialogQueue()
3119 // set the flag so we don't pause waiting for another permit and semaphore
3120 // the current task to begin
3121 dialogPause = false;
3126 protected void snapShotWindow_actionPerformed(ActionEvent e)
3130 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3131 "View of Desktop", getWidth(), getHeight(), of = new File(
3132 "Jalview_snapshot" + System.currentTimeMillis()
3133 + ".eps"), "View of desktop", null, 0, false);
3136 paintAll(im.getGraphics());
3138 } catch (Exception q)
3140 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3144 Cache.log.info("Successfully written snapshot to file "
3145 + of.getAbsolutePath());
3149 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3150 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3151 * and location last time the view was expanded (if any). However it does not
3152 * remember the split pane divider location - this is set to match the
3153 * 'exploding' frame.
3157 public void explodeViews(SplitFrame sf)
3159 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3160 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3161 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3163 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3165 int viewCount = topPanels.size();
3172 * Processing in reverse order works, forwards order leaves the first panels
3173 * not visible. I don't know why!
3175 for (int i = viewCount - 1; i >= 0; i--)
3178 * Make new top and bottom frames. These take over the respective
3179 * AlignmentPanel objects, including their AlignmentViewports, so the
3180 * cdna/protein relationships between the viewports is carried over to the
3183 * explodedGeometry holds the (x, y) position of the previously exploded
3184 * SplitFrame, and the (width, height) of the AlignFrame component
3186 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3187 AlignFrame newTopFrame = new AlignFrame(topPanel);
3188 newTopFrame.setSize(oldTopFrame.getSize());
3189 newTopFrame.setVisible(true);
3190 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3191 .getExplodedGeometry();
3192 if (geometry != null)
3194 newTopFrame.setSize(geometry.getSize());
3197 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3198 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3199 newBottomFrame.setSize(oldBottomFrame.getSize());
3200 newBottomFrame.setVisible(true);
3201 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3202 .getExplodedGeometry();
3203 if (geometry != null)
3205 newBottomFrame.setSize(geometry.getSize());
3208 topPanel.av.setGatherViewsHere(false);
3209 bottomPanel.av.setGatherViewsHere(false);
3210 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3212 if (geometry != null)
3214 splitFrame.setLocation(geometry.getLocation());
3216 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3220 * Clear references to the panels (now relocated in the new SplitFrames)
3221 * before closing the old SplitFrame.
3224 bottomPanels.clear();
3229 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3230 * back into the given SplitFrame as additional views. Note that the gathered
3231 * frames may themselves have multiple views.
3235 public void gatherViews(GSplitFrame source)
3238 * special handling of explodedGeometry for a view within a SplitFrame: - it
3239 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3240 * height) of the AlignFrame component
3242 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3243 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3244 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3245 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3246 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3247 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3249 myTopFrame.viewport.setGatherViewsHere(true);
3250 myBottomFrame.viewport.setGatherViewsHere(true);
3251 String topViewId = myTopFrame.viewport.getSequenceSetId();
3252 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3254 JInternalFrame[] frames = desktop.getAllFrames();
3255 for (JInternalFrame frame : frames)
3257 if (frame instanceof SplitFrame && frame != source)
3259 SplitFrame sf = (SplitFrame) frame;
3260 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3261 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3262 boolean gatherThis = false;
3263 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3265 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3266 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3267 if (topViewId.equals(topPanel.av.getSequenceSetId())
3268 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3271 topPanel.av.setGatherViewsHere(false);
3272 bottomPanel.av.setGatherViewsHere(false);
3273 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3274 topFrame.getSize()));
3275 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3276 .getLocation(), bottomFrame.getSize()));
3277 myTopFrame.addAlignmentPanel(topPanel, false);
3278 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3284 topFrame.getAlignPanels().clear();
3285 bottomFrame.getAlignPanels().clear();
3292 * The dust settles...give focus to the tab we did this from.
3294 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3297 public static groovy.ui.Console getGroovyConsole()
3299 return groovyConsole;
3302 public static void transferFromDropTarget(List<String> files,
3303 List<DataSourceType> protocols, DropTargetDropEvent evt,
3308 DataFlavor uriListFlavor = new DataFlavor(
3309 "text/uri-list;class=java.lang.String");
3310 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3312 // Works on Windows and MacOSX
3313 Cache.log.debug("Drop handled as javaFileListFlavor");
3314 for (Object file : (List) t
3315 .getTransferData(DataFlavor.javaFileListFlavor))
3317 files.add(((File) file).toString());
3318 protocols.add(DataSourceType.FILE);
3323 // Unix like behaviour
3324 boolean added = false;
3326 if (t.isDataFlavorSupported(uriListFlavor))
3328 Cache.log.debug("Drop handled as uriListFlavor");
3329 // This is used by Unix drag system
3330 data = (String) t.getTransferData(uriListFlavor);
3334 // fallback to text: workaround - on OSX where there's a JVM bug
3335 Cache.log.debug("standard URIListFlavor failed. Trying text");
3336 // try text fallback
3337 data = (String) t.getTransferData(new DataFlavor(
3338 "text/plain;class=java.lang.String"));
3339 if (Cache.log.isDebugEnabled())
3341 Cache.log.debug("fallback returned " + data);
3344 while (protocols.size() < files.size())
3346 Cache.log.debug("Adding missing FILE protocol for "
3347 + files.get(protocols.size()));
3348 protocols.add(DataSourceType.FILE);
3350 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3351 data, "\r\n"); st.hasMoreTokens();)
3354 String s = st.nextToken();
3355 if (s.startsWith("#"))
3357 // the line is a comment (as per the RFC 2483)
3360 java.net.URI uri = new java.net.URI(s);
3361 if (uri.getScheme().toLowerCase().startsWith("http"))
3363 protocols.add(DataSourceType.URL);
3364 files.add(uri.toString());
3368 // otherwise preserve old behaviour: catch all for file objects
3369 java.io.File file = new java.io.File(uri);
3370 protocols.add(DataSourceType.FILE);
3371 files.add(file.toString());
3374 if (Cache.log.isDebugEnabled())
3376 if (data == null || !added)
3379 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3380 for (DataFlavor fl : t.getTransferDataFlavors())
3382 Cache.log.debug("Supported transfer dataflavor: "
3384 Object df = t.getTransferData(fl);
3387 Cache.log.debug("Retrieves: " + df);
3391 Cache.log.debug("Retrieved nothing");
3400 * Sets the Preferences property for experimental features to True or False
3401 * depending on the state of the controlling menu item
3404 protected void showExperimental_actionPerformed(boolean selected)
3406 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));