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.InputEvent;
72 import java.awt.event.KeyEvent;
73 import java.awt.event.MouseAdapter;
74 import java.awt.event.MouseEvent;
75 import java.awt.event.WindowAdapter;
76 import java.awt.event.WindowEvent;
77 import java.beans.PropertyChangeEvent;
78 import java.beans.PropertyChangeListener;
79 import java.io.BufferedInputStream;
81 import java.io.FileOutputStream;
82 import java.io.IOException;
84 import java.util.ArrayList;
85 import java.util.Hashtable;
86 import java.util.List;
87 import java.util.ListIterator;
88 import java.util.StringTokenizer;
89 import java.util.Vector;
90 import java.util.concurrent.ExecutorService;
91 import java.util.concurrent.Executors;
92 import java.util.concurrent.Semaphore;
94 import javax.swing.AbstractAction;
95 import javax.swing.Box;
96 import javax.swing.BoxLayout;
97 import javax.swing.DefaultDesktopManager;
98 import javax.swing.DesktopManager;
99 import javax.swing.JButton;
100 import javax.swing.JCheckBox;
101 import javax.swing.JComboBox;
102 import javax.swing.JComponent;
103 import javax.swing.JDesktopPane;
104 import javax.swing.JFrame;
105 import javax.swing.JInternalFrame;
106 import javax.swing.JLabel;
107 import javax.swing.JMenuItem;
108 import javax.swing.JPanel;
109 import javax.swing.JPopupMenu;
110 import javax.swing.JProgressBar;
111 import javax.swing.KeyStroke;
112 import javax.swing.SwingUtilities;
113 import javax.swing.event.HyperlinkEvent;
114 import javax.swing.event.HyperlinkEvent.EventType;
115 import javax.swing.event.InternalFrameAdapter;
116 import javax.swing.event.InternalFrameEvent;
117 import javax.swing.event.MenuEvent;
118 import javax.swing.event.MenuListener;
125 * @version $Revision: 1.155 $
127 public class Desktop extends jalview.jbgui.GDesktop
128 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
129 jalview.api.StructureSelectionManagerProvider
131 private static int DEFAULT_MIN_WIDTH = 300;
133 private static int DEFAULT_MIN_HEIGHT = 250;
135 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
137 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
139 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
141 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
144 * news reader - null if it was never started.
146 private BlogReader jvnews = null;
148 private File projectFile;
152 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
154 public void addJalviewPropertyChangeListener(
155 PropertyChangeListener listener)
157 changeSupport.addJalviewPropertyChangeListener(listener);
161 * @param propertyName
163 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
164 * java.beans.PropertyChangeListener)
166 public void addJalviewPropertyChangeListener(String propertyName,
167 PropertyChangeListener listener)
169 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
173 * @param propertyName
175 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
176 * java.beans.PropertyChangeListener)
178 public void removeJalviewPropertyChangeListener(String propertyName,
179 PropertyChangeListener listener)
181 changeSupport.removeJalviewPropertyChangeListener(propertyName,
185 /** Singleton Desktop instance */
186 public static Desktop instance;
188 public static MyDesktopPane desktop;
190 static int openFrameCount = 0;
192 static final int xOffset = 30;
194 static final int yOffset = 30;
196 public static jalview.ws.jws1.Discoverer discoverer;
198 public static Object[] jalviewClipboard;
200 public static boolean internalCopy = false;
202 static int fileLoadingCount = 0;
204 class MyDesktopManager implements DesktopManager
207 private DesktopManager delegate;
209 public MyDesktopManager(DesktopManager delegate)
211 this.delegate = delegate;
215 public void activateFrame(JInternalFrame f)
219 delegate.activateFrame(f);
220 } catch (NullPointerException npe)
222 Point p = getMousePosition();
223 instance.showPasteMenu(p.x, p.y);
228 public void beginDraggingFrame(JComponent f)
230 delegate.beginDraggingFrame(f);
234 public void beginResizingFrame(JComponent f, int direction)
236 delegate.beginResizingFrame(f, direction);
240 public void closeFrame(JInternalFrame f)
242 delegate.closeFrame(f);
246 public void deactivateFrame(JInternalFrame f)
248 delegate.deactivateFrame(f);
252 public void deiconifyFrame(JInternalFrame f)
254 delegate.deiconifyFrame(f);
258 public void dragFrame(JComponent f, int newX, int newY)
264 delegate.dragFrame(f, newX, newY);
268 public void endDraggingFrame(JComponent f)
270 delegate.endDraggingFrame(f);
275 public void endResizingFrame(JComponent f)
277 delegate.endResizingFrame(f);
282 public void iconifyFrame(JInternalFrame f)
284 delegate.iconifyFrame(f);
288 public void maximizeFrame(JInternalFrame f)
290 delegate.maximizeFrame(f);
294 public void minimizeFrame(JInternalFrame f)
296 delegate.minimizeFrame(f);
300 public void openFrame(JInternalFrame f)
302 delegate.openFrame(f);
306 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
313 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
317 public void setBoundsForFrame(JComponent f, int newX, int newY,
318 int newWidth, int newHeight)
320 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
323 // All other methods, simply delegate
328 * Creates a new Desktop object.
333 * A note to implementors. It is ESSENTIAL that any activities that might
334 * block are spawned off as threads rather than waited for during this
338 doVamsasClientCheck();
340 doConfigureStructurePrefs();
341 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
342 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
345 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
347 desktop = new MyDesktopPane(selmemusage);
348 showMemusage.setSelected(selmemusage);
349 desktop.setBackground(Color.white);
350 getContentPane().setLayout(new BorderLayout());
351 // alternate config - have scrollbars - see notes in JAL-153
352 // JScrollPane sp = new JScrollPane();
353 // sp.getViewport().setView(desktop);
354 // getContentPane().add(sp, BorderLayout.CENTER);
355 getContentPane().add(desktop, BorderLayout.CENTER);
356 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
358 // This line prevents Windows Look&Feel resizing all new windows to maximum
359 // if previous window was maximised
360 desktop.setDesktopManager(
361 new MyDesktopManager(
362 (Platform.isWindows() ? new DefaultDesktopManager()
364 ? new AquaInternalFrameManager(
365 desktop.getDesktopManager())
366 : desktop.getDesktopManager())));
368 Rectangle dims = getLastKnownDimensions("");
375 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
376 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
379 jconsole = new Console(this, showjconsole);
380 // add essential build information
382 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
383 + "\n" + "Jalview Installation: "
384 + jalview.bin.Cache.getDefault("INSTALLATION",
386 + "\n" + "Build Date: "
387 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
388 + "\n" + "Java version: "
389 + 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 experimentalFeatures.setSelected(showExperimental());
400 getIdentifiersOrgData();
404 this.addWindowListener(new WindowAdapter()
407 public void windowClosing(WindowEvent evt)
414 this.addMouseListener(ma = new MouseAdapter()
417 public void mousePressed(MouseEvent evt)
419 if (evt.isPopupTrigger()) // Mac
421 showPasteMenu(evt.getX(), evt.getY());
426 public void mouseReleased(MouseEvent evt)
428 if (evt.isPopupTrigger()) // Windows
430 showPasteMenu(evt.getX(), evt.getY());
434 desktop.addMouseListener(ma);
436 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
437 // Spawn a thread that shows the splashscreen
438 SwingUtilities.invokeLater(new Runnable()
447 // Thread off a new instance of the file chooser - this reduces the time it
448 // takes to open it later on.
449 new Thread(new Runnable()
454 Cache.log.debug("Filechooser init thread started.");
455 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
456 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
458 Cache.log.debug("Filechooser init thread finished.");
461 // Add the service change listener
462 changeSupport.addJalviewPropertyChangeListener("services",
463 new PropertyChangeListener()
467 public void propertyChange(PropertyChangeEvent evt)
469 Cache.log.debug("Firing service changed event for "
470 + evt.getNewValue());
471 JalviewServicesChanged(evt);
478 * Answers true if user preferences to enable experimental features is True
483 public boolean showExperimental()
485 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
486 Boolean.FALSE.toString());
487 return Boolean.valueOf(experimental).booleanValue();
490 public void doConfigureStructurePrefs()
492 // configure services
493 StructureSelectionManager ssm = StructureSelectionManager
494 .getStructureSelectionManager(this);
495 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
497 ssm.setAddTempFacAnnot(jalview.bin.Cache
498 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
499 ssm.setProcessSecondaryStructure(jalview.bin.Cache
500 .getDefault(Preferences.STRUCT_FROM_PDB, true));
501 ssm.setSecStructServices(
502 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
506 ssm.setAddTempFacAnnot(false);
507 ssm.setProcessSecondaryStructure(false);
508 ssm.setSecStructServices(false);
512 public void checkForNews()
514 final Desktop me = this;
515 // Thread off the news reader, in case there are connection problems.
516 addDialogThread(new Runnable()
521 Cache.log.debug("Starting news thread.");
523 jvnews = new BlogReader(me);
524 showNews.setVisible(true);
525 Cache.log.debug("Completed news thread.");
530 public void getIdentifiersOrgData()
532 // Thread off the identifiers fetcher
533 addDialogThread(new Runnable()
538 Cache.log.debug("Downloading data from identifiers.org");
539 UrlDownloadClient client = new UrlDownloadClient();
542 client.download(IdOrgSettings.getUrl(),
543 IdOrgSettings.getDownloadLocation());
544 } catch (IOException e)
546 Cache.log.debug("Exception downloading identifiers.org data"
554 protected void showNews_actionPerformed(ActionEvent e)
556 showNews(showNews.isSelected());
559 void showNews(boolean visible)
562 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
563 showNews.setSelected(visible);
564 if (visible && !jvnews.isVisible())
566 new Thread(new Runnable()
571 long now = System.currentTimeMillis();
572 Desktop.instance.setProgressBar(
573 MessageManager.getString("status.refreshing_news"),
575 jvnews.refreshNews();
576 Desktop.instance.setProgressBar(null, now);
585 * recover the last known dimensions for a jalview window
588 * - empty string is desktop, all other windows have unique prefix
589 * @return null or last known dimensions scaled to current geometry (if last
590 * window geom was known)
592 Rectangle getLastKnownDimensions(String windowName)
594 // TODO: lock aspect ratio for scaling desktop Bug #0058199
595 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
596 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
597 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
598 String width = jalview.bin.Cache
599 .getProperty(windowName + "SCREEN_WIDTH");
600 String height = jalview.bin.Cache
601 .getProperty(windowName + "SCREEN_HEIGHT");
602 if ((x != null) && (y != null) && (width != null) && (height != null))
604 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
605 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
606 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
608 // attempt #1 - try to cope with change in screen geometry - this
609 // version doesn't preserve original jv aspect ratio.
610 // take ratio of current screen size vs original screen size.
611 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
612 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
613 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
614 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
615 // rescale the bounds depending upon the current screen geometry.
616 ix = (int) (ix * sw);
617 iw = (int) (iw * sw);
618 iy = (int) (iy * sh);
619 ih = (int) (ih * sh);
620 while (ix >= screenSize.width)
622 jalview.bin.Cache.log.debug(
623 "Window geometry location recall error: shifting horizontal to within screenbounds.");
624 ix -= screenSize.width;
626 while (iy >= screenSize.height)
628 jalview.bin.Cache.log.debug(
629 "Window geometry location recall error: shifting vertical to within screenbounds.");
630 iy -= screenSize.height;
632 jalview.bin.Cache.log.debug(
633 "Got last known dimensions for " + windowName + ": x:" + ix
634 + " y:" + iy + " width:" + iw + " height:" + ih);
636 // return dimensions for new instance
637 return new Rectangle(ix, iy, iw, ih);
642 private void doVamsasClientCheck()
644 if (jalview.bin.Cache.vamsasJarsPresent())
646 setupVamsasDisconnectedGui();
647 VamsasMenu.setVisible(true);
648 final Desktop us = this;
649 VamsasMenu.addMenuListener(new MenuListener()
651 // this listener remembers when the menu was first selected, and
652 // doesn't rebuild the session list until it has been cleared and
654 boolean refresh = true;
657 public void menuCanceled(MenuEvent e)
663 public void menuDeselected(MenuEvent e)
669 public void menuSelected(MenuEvent e)
673 us.buildVamsasStMenu();
678 vamsasStart.setVisible(true);
682 void showPasteMenu(int x, int y)
684 JPopupMenu popup = new JPopupMenu();
685 JMenuItem item = new JMenuItem(
686 MessageManager.getString("label.paste_new_window"));
687 item.addActionListener(new ActionListener()
690 public void actionPerformed(ActionEvent evt)
697 popup.show(this, x, y);
704 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
705 Transferable contents = c.getContents(this);
707 if (contents != null)
709 String file = (String) contents
710 .getTransferData(DataFlavor.stringFlavor);
712 FileFormatI format = new IdentifyFile().identify(file,
713 DataSourceType.PASTE);
715 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
718 } catch (Exception ex)
721 "Unable to paste alignment from system clipboard:\n" + ex);
726 * Adds and opens the given frame to the desktop
737 public static synchronized void addInternalFrame(
738 final JInternalFrame frame, String title, int w, int h)
740 addInternalFrame(frame, title, true, w, h, true, false);
744 * Add an internal frame to the Jalview desktop
751 * When true, display frame immediately, otherwise, caller must call
752 * setVisible themselves.
758 public static synchronized void addInternalFrame(
759 final JInternalFrame frame, String title, boolean makeVisible,
762 addInternalFrame(frame, title, makeVisible, w, h, true, false);
766 * Add an internal frame to the Jalview desktop and make it visible
779 public static synchronized void addInternalFrame(
780 final JInternalFrame frame, String title, int w, int h,
783 addInternalFrame(frame, title, true, w, h, resizable, false);
787 * Add an internal frame to the Jalview desktop
794 * When true, display frame immediately, otherwise, caller must call
795 * setVisible themselves.
802 * @param ignoreMinSize
803 * Do not set the default minimum size for frame
805 public static synchronized void addInternalFrame(
806 final JInternalFrame frame, String title, boolean makeVisible,
807 int w, int h, boolean resizable, boolean ignoreMinSize)
810 // TODO: allow callers to determine X and Y position of frame (eg. via
812 // TODO: consider fixing method to update entries in the window submenu with
813 // the current window title
815 frame.setTitle(title);
816 if (frame.getWidth() < 1 || frame.getHeight() < 1)
820 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
821 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
822 // IF JALVIEW IS RUNNING HEADLESS
823 // ///////////////////////////////////////////////
824 if (instance == null || (System.getProperty("java.awt.headless") != null
825 && System.getProperty("java.awt.headless").equals("true")))
834 frame.setMinimumSize(
835 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
837 // Set default dimension for Alignment Frame window.
838 // The Alignment Frame window could be added from a number of places,
840 // I did this here in order not to miss out on any Alignment frame.
841 if (frame instanceof AlignFrame)
843 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
844 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
848 frame.setVisible(makeVisible);
849 frame.setClosable(true);
850 frame.setResizable(resizable);
851 frame.setMaximizable(resizable);
852 frame.setIconifiable(resizable);
854 if (frame.getX() < 1 && frame.getY() < 1)
856 frame.setLocation(xOffset * openFrameCount,
857 yOffset * ((openFrameCount - 1) % 10) + yOffset);
861 * add an entry for the new frame in the Window menu
862 * (and remove it when the frame is closed)
864 final JMenuItem menuItem = new JMenuItem(title);
865 frame.addInternalFrameListener(new InternalFrameAdapter()
868 public void internalFrameActivated(InternalFrameEvent evt)
870 JInternalFrame itf = desktop.getSelectedFrame();
873 if (itf instanceof AlignFrame)
875 Jalview.setCurrentAlignFrame((AlignFrame) itf);
882 public void internalFrameClosed(InternalFrameEvent evt)
884 PaintRefresher.RemoveComponent(frame);
887 * defensive check to prevent frames being
888 * added half off the window
890 if (openFrameCount > 0)
896 * ensure no reference to alignFrame retained by menu item listener
898 if (menuItem.getActionListeners().length > 0)
900 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
902 windowMenu.remove(menuItem);
908 menuItem.addActionListener(new ActionListener()
911 public void actionPerformed(ActionEvent e)
915 frame.setSelected(true);
916 frame.setIcon(false);
917 } catch (java.beans.PropertyVetoException ex)
924 setKeyBindings(frame);
928 windowMenu.add(menuItem);
933 frame.setSelected(true);
934 frame.requestFocus();
935 } catch (java.beans.PropertyVetoException ve)
937 } catch (java.lang.ClassCastException cex)
940 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
946 * Add key bindings to a JInternalFrame so that ctrl-W and cmd-W will close
950 * the JInternalFrame to set the key bindings for
952 private static void setKeyBindings(JInternalFrame frame)
954 // create a close action
955 class CloseAction extends AbstractAction
957 private JInternalFrame frame;
959 CloseAction(JInternalFrame frame)
965 public void actionPerformed(ActionEvent e)
971 final CloseAction closeAction = new CloseAction(frame);
973 // set up keybindings for ctrl-W and cmd-W
974 KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
975 InputEvent.CTRL_DOWN_MASK);
976 KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
977 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
978 frame.getInputMap().put(ctrlWKey, ctrlWKey.toString());
979 frame.getActionMap().put(ctrlWKey.toString(), closeAction);
980 frame.getInputMap().put(cmdWKey, ctrlWKey.toString());
981 frame.getActionMap().put(cmdWKey.toString(), closeAction);
985 public void lostOwnership(Clipboard clipboard, Transferable contents)
989 Desktop.jalviewClipboard = null;
992 internalCopy = false;
996 public void dragEnter(DropTargetDragEvent evt)
1001 public void dragExit(DropTargetEvent evt)
1006 public void dragOver(DropTargetDragEvent evt)
1011 public void dropActionChanged(DropTargetDragEvent evt)
1022 public void drop(DropTargetDropEvent evt)
1024 boolean success = true;
1025 // JAL-1552 - acceptDrop required before getTransferable call for
1026 // Java's Transferable for native dnd
1027 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1028 Transferable t = evt.getTransferable();
1029 List<String> files = new ArrayList<>();
1030 List<DataSourceType> protocols = new ArrayList<>();
1034 Desktop.transferFromDropTarget(files, protocols, evt, t);
1035 } catch (Exception e)
1037 e.printStackTrace();
1045 for (int i = 0; i < files.size(); i++)
1047 String file = files.get(i).toString();
1048 DataSourceType protocol = (protocols == null)
1049 ? DataSourceType.FILE
1051 FileFormatI format = null;
1053 if (file.endsWith(".jar"))
1055 format = FileFormat.Jalview;
1060 format = new IdentifyFile().identify(file, protocol);
1063 new FileLoader().LoadFile(file, protocol, format);
1066 } catch (Exception ex)
1071 evt.dropComplete(success); // need this to ensure input focus is properly
1072 // transfered to any new windows created
1082 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1084 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1085 JalviewFileChooser chooser = JalviewFileChooser
1086 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1088 chooser.setFileView(new JalviewFileView());
1089 chooser.setDialogTitle(
1090 MessageManager.getString("label.open_local_file"));
1091 chooser.setToolTipText(MessageManager.getString("action.open"));
1093 int value = chooser.showOpenDialog(this);
1095 if (value == JalviewFileChooser.APPROVE_OPTION)
1097 String choice = chooser.getSelectedFile().getPath();
1098 Cache.setProperty("LAST_DIRECTORY",
1099 chooser.getSelectedFile().getParent());
1101 FileFormatI format = chooser.getSelectedFormat();
1104 * Call IdentifyFile to verify the file contains what its extension implies.
1105 * Skip this step for dynamically added file formats, because
1106 * IdentifyFile does not know how to recognise them.
1108 if (FileFormats.getInstance().isIdentifiable(format))
1112 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1113 } catch (FileFormatException e)
1115 // format = null; //??
1119 if (viewport != null)
1121 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1126 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1138 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1140 // This construct allows us to have a wider textfield
1142 JLabel label = new JLabel(
1143 MessageManager.getString("label.input_file_url"));
1144 final JComboBox history = new JComboBox();
1146 JPanel panel = new JPanel(new GridLayout(2, 1));
1149 history.setPreferredSize(new Dimension(400, 20));
1150 history.setEditable(true);
1151 history.addItem("http://www.");
1153 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1157 if (historyItems != null)
1159 st = new StringTokenizer(historyItems, "\t");
1161 while (st.hasMoreTokens())
1163 history.addItem(st.nextElement());
1167 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1168 MessageManager.getString("label.input_alignment_from_url"),
1169 JvOptionPane.OK_CANCEL_OPTION);
1171 if (reply != JvOptionPane.OK_OPTION)
1176 String url = history.getSelectedItem().toString();
1178 if (url.toLowerCase().endsWith(".jar"))
1180 if (viewport != null)
1182 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1183 FileFormat.Jalview);
1187 new FileLoader().LoadFile(url, DataSourceType.URL,
1188 FileFormat.Jalview);
1193 FileFormatI format = null;
1196 format = new IdentifyFile().identify(url, DataSourceType.URL);
1197 } catch (FileFormatException e)
1199 // TODO revise error handling, distinguish between
1200 // URL not found and response not valid
1205 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1206 MessageManager.formatMessage("label.couldnt_locate",
1209 MessageManager.getString("label.url_not_found"),
1210 JvOptionPane.WARNING_MESSAGE);
1215 if (viewport != null)
1217 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1222 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1228 * Opens the CutAndPaste window for the user to paste an alignment in to
1231 * - if not null, the pasted alignment is added to the current
1232 * alignment; if null, to a new alignment window
1235 public void inputTextboxMenuItem_actionPerformed(
1236 AlignmentViewPanel viewPanel)
1238 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1239 cap.setForInput(viewPanel);
1240 Desktop.addInternalFrame(cap,
1241 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1251 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1252 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1254 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1255 screen.height + "");
1256 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1257 getWidth(), getHeight()));
1259 if (jconsole != null)
1261 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1262 jconsole.stopConsole();
1266 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1269 if (dialogExecutor != null)
1271 dialogExecutor.shutdownNow();
1273 closeAll_actionPerformed(null);
1275 if (groovyConsole != null)
1277 // suppress a possible repeat prompt to save script
1278 groovyConsole.setDirty(false);
1279 groovyConsole.exit();
1284 private void storeLastKnownDimensions(String string, Rectangle jc)
1286 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1287 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1288 + " height:" + jc.height);
1290 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1291 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1292 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1293 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1303 public void aboutMenuItem_actionPerformed(ActionEvent e)
1305 // StringBuffer message = getAboutMessage(false);
1306 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1308 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1309 new Thread(new Runnable()
1314 new SplashScreen(true);
1319 public StringBuffer getAboutMessage(boolean shortv)
1321 StringBuffer message = new StringBuffer();
1322 message.append("<html>");
1325 message.append("<h1><strong>Version: "
1326 + jalview.bin.Cache.getProperty("VERSION")
1327 + "</strong></h1>");
1328 message.append("<strong>Last Updated: <em>"
1329 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1330 + "</em></strong>");
1336 message.append("<strong>Version "
1337 + jalview.bin.Cache.getProperty("VERSION")
1338 + "; last updated: "
1339 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1342 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1343 .equals("Checking"))
1345 message.append("<br>...Checking latest version...</br>");
1347 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1348 .equals(jalview.bin.Cache.getProperty("VERSION")))
1350 boolean red = false;
1351 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1352 .indexOf("automated build") == -1)
1355 // Displayed when code version and jnlp version do not match and code
1356 // version is not a development build
1357 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1360 message.append("<br>!! Version "
1361 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1363 + " is available for download from "
1364 + jalview.bin.Cache.getDefault("www.jalview.org",
1365 "http://www.jalview.org")
1369 message.append("</div>");
1372 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1374 "The Jalview Authors (See AUTHORS file for current list)")
1375 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1376 + "<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"
1377 + "<br><br>If you use Jalview, please cite:"
1378 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1379 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1380 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1392 public void documentationMenuItem_actionPerformed(ActionEvent e)
1396 Help.showHelpWindow();
1397 } catch (Exception ex)
1403 public void closeAll_actionPerformed(ActionEvent e)
1405 // TODO show a progress bar while closing?
1406 JInternalFrame[] frames = desktop.getAllFrames();
1407 for (int i = 0; i < frames.length; i++)
1411 frames[i].setClosed(true);
1412 } catch (java.beans.PropertyVetoException ex)
1416 Jalview.setCurrentAlignFrame(null);
1417 System.out.println("ALL CLOSED");
1418 if (v_client != null)
1420 // TODO clear binding to vamsas document objects on close_all
1424 * reset state of singleton objects as appropriate (clear down session state
1425 * when all windows are closed)
1427 StructureSelectionManager ssm = StructureSelectionManager
1428 .getStructureSelectionManager(this);
1437 public void raiseRelated_actionPerformed(ActionEvent e)
1439 reorderAssociatedWindows(false, false);
1443 public void minimizeAssociated_actionPerformed(ActionEvent e)
1445 reorderAssociatedWindows(true, false);
1448 void closeAssociatedWindows()
1450 reorderAssociatedWindows(false, true);
1456 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1460 protected void garbageCollect_actionPerformed(ActionEvent e)
1462 // We simply collect the garbage
1463 jalview.bin.Cache.log.debug("Collecting garbage...");
1465 jalview.bin.Cache.log.debug("Finished garbage collection.");
1472 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1476 protected void showMemusage_actionPerformed(ActionEvent e)
1478 desktop.showMemoryUsage(showMemusage.isSelected());
1485 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1489 protected void showConsole_actionPerformed(ActionEvent e)
1491 showConsole(showConsole.isSelected());
1494 Console jconsole = null;
1497 * control whether the java console is visible or not
1501 void showConsole(boolean selected)
1503 showConsole.setSelected(selected);
1504 // TODO: decide if we should update properties file
1505 Cache.setProperty("SHOW_JAVA_CONSOLE",
1506 Boolean.valueOf(selected).toString());
1507 jconsole.setVisible(selected);
1510 void reorderAssociatedWindows(boolean minimize, boolean close)
1512 JInternalFrame[] frames = desktop.getAllFrames();
1513 if (frames == null || frames.length < 1)
1518 AlignmentViewport source = null, target = null;
1519 if (frames[0] instanceof AlignFrame)
1521 source = ((AlignFrame) frames[0]).getCurrentView();
1523 else if (frames[0] instanceof TreePanel)
1525 source = ((TreePanel) frames[0]).getViewPort();
1527 else if (frames[0] instanceof PCAPanel)
1529 source = ((PCAPanel) frames[0]).av;
1531 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1533 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1538 for (int i = 0; i < frames.length; i++)
1541 if (frames[i] == null)
1545 if (frames[i] instanceof AlignFrame)
1547 target = ((AlignFrame) frames[i]).getCurrentView();
1549 else if (frames[i] instanceof TreePanel)
1551 target = ((TreePanel) frames[i]).getViewPort();
1553 else if (frames[i] instanceof PCAPanel)
1555 target = ((PCAPanel) frames[i]).av;
1557 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1559 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1562 if (source == target)
1568 frames[i].setClosed(true);
1572 frames[i].setIcon(minimize);
1575 frames[i].toFront();
1579 } catch (java.beans.PropertyVetoException ex)
1594 protected void preferences_actionPerformed(ActionEvent e)
1606 public void saveState_actionPerformed(ActionEvent e)
1608 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1611 chooser.setFileView(new JalviewFileView());
1612 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1614 int value = chooser.showSaveDialog(this);
1616 if (value == JalviewFileChooser.APPROVE_OPTION)
1618 final Desktop me = this;
1619 final java.io.File choice = chooser.getSelectedFile();
1620 setProjectFile(choice);
1622 new Thread(new Runnable()
1627 // TODO: refactor to Jalview desktop session controller action.
1628 setProgressBar(MessageManager.formatMessage(
1629 "label.saving_jalview_project", new Object[]
1630 { choice.getName() }), choice.hashCode());
1631 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1632 choice.getParent());
1633 // TODO catch and handle errors for savestate
1634 // TODO prevent user from messing with the Desktop whilst we're saving
1637 new Jalview2XML().saveState(choice);
1638 } catch (OutOfMemoryError oom)
1641 "Whilst saving current state to " + choice.getName(),
1643 } catch (Exception ex)
1646 "Problems whilst trying to save to " + choice.getName(),
1648 JvOptionPane.showMessageDialog(me,
1649 MessageManager.formatMessage(
1650 "label.error_whilst_saving_current_state_to",
1652 { choice.getName() }),
1653 MessageManager.getString("label.couldnt_save_project"),
1654 JvOptionPane.WARNING_MESSAGE);
1656 setProgressBar(null, choice.hashCode());
1662 private void setProjectFile(File choice)
1664 this.projectFile = choice;
1667 public File getProjectFile()
1669 return this.projectFile;
1679 public void loadState_actionPerformed(ActionEvent e)
1681 JalviewFileChooser chooser = new JalviewFileChooser(
1682 Cache.getProperty("LAST_DIRECTORY"), new String[]
1685 { "Jalview Project", "Jalview Project (old)" },
1687 chooser.setFileView(new JalviewFileView());
1688 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1690 int value = chooser.showOpenDialog(this);
1692 if (value == JalviewFileChooser.APPROVE_OPTION)
1694 final File selectedFile = chooser.getSelectedFile();
1695 setProjectFile(selectedFile);
1696 final String choice = selectedFile.getAbsolutePath();
1697 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1698 new Thread(new Runnable()
1703 setProgressBar(MessageManager.formatMessage(
1704 "label.loading_jalview_project", new Object[]
1705 { choice }), choice.hashCode());
1708 new Jalview2XML().loadJalviewAlign(choice);
1709 } catch (OutOfMemoryError oom)
1711 new OOMWarning("Whilst loading project from " + choice, oom);
1712 } catch (Exception ex)
1715 "Problems whilst loading project from " + choice, ex);
1716 JvOptionPane.showMessageDialog(Desktop.desktop,
1717 MessageManager.formatMessage(
1718 "label.error_whilst_loading_project_from",
1721 MessageManager.getString("label.couldnt_load_project"),
1722 JvOptionPane.WARNING_MESSAGE);
1724 setProgressBar(null, choice.hashCode());
1731 public void inputSequence_actionPerformed(ActionEvent e)
1733 new SequenceFetcher(this);
1736 JPanel progressPanel;
1738 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1740 public void startLoading(final String fileName)
1742 if (fileLoadingCount == 0)
1744 fileLoadingPanels.add(addProgressPanel(MessageManager
1745 .formatMessage("label.loading_file", new Object[]
1751 private JPanel addProgressPanel(String string)
1753 if (progressPanel == null)
1755 progressPanel = new JPanel(new GridLayout(1, 1));
1756 totalProgressCount = 0;
1757 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1759 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1760 JProgressBar progressBar = new JProgressBar();
1761 progressBar.setIndeterminate(true);
1763 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1765 thisprogress.add(progressBar, BorderLayout.CENTER);
1766 progressPanel.add(thisprogress);
1767 ((GridLayout) progressPanel.getLayout()).setRows(
1768 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1769 ++totalProgressCount;
1770 instance.validate();
1771 return thisprogress;
1774 int totalProgressCount = 0;
1776 private void removeProgressPanel(JPanel progbar)
1778 if (progressPanel != null)
1780 synchronized (progressPanel)
1782 progressPanel.remove(progbar);
1783 GridLayout gl = (GridLayout) progressPanel.getLayout();
1784 gl.setRows(gl.getRows() - 1);
1785 if (--totalProgressCount < 1)
1787 this.getContentPane().remove(progressPanel);
1788 progressPanel = null;
1795 public void stopLoading()
1798 if (fileLoadingCount < 1)
1800 while (fileLoadingPanels.size() > 0)
1802 removeProgressPanel(fileLoadingPanels.remove(0));
1804 fileLoadingPanels.clear();
1805 fileLoadingCount = 0;
1810 public static int getViewCount(String alignmentId)
1812 AlignmentViewport[] aps = getViewports(alignmentId);
1813 return (aps == null) ? 0 : aps.length;
1818 * @param alignmentId
1819 * - if null, all sets are returned
1820 * @return all AlignmentPanels concerning the alignmentId sequence set
1822 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1824 if (Desktop.desktop == null)
1826 // no frames created and in headless mode
1827 // TODO: verify that frames are recoverable when in headless mode
1830 List<AlignmentPanel> aps = new ArrayList<>();
1831 AlignFrame[] frames = getAlignFrames();
1836 for (AlignFrame af : frames)
1838 for (AlignmentPanel ap : af.alignPanels)
1840 if (alignmentId == null
1841 || alignmentId.equals(ap.av.getSequenceSetId()))
1847 if (aps.size() == 0)
1851 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1856 * get all the viewports on an alignment.
1858 * @param sequenceSetId
1859 * unique alignment id (may be null - all viewports returned in that
1861 * @return all viewports on the alignment bound to sequenceSetId
1863 public static AlignmentViewport[] getViewports(String sequenceSetId)
1865 List<AlignmentViewport> viewp = new ArrayList<>();
1866 if (desktop != null)
1868 AlignFrame[] frames = Desktop.getAlignFrames();
1870 for (AlignFrame afr : frames)
1872 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1873 .equals(sequenceSetId))
1875 if (afr.alignPanels != null)
1877 for (AlignmentPanel ap : afr.alignPanels)
1879 if (sequenceSetId == null
1880 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1888 viewp.add(afr.getViewport());
1892 if (viewp.size() > 0)
1894 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1901 * Explode the views in the given frame into separate AlignFrame
1905 public static void explodeViews(AlignFrame af)
1907 int size = af.alignPanels.size();
1913 for (int i = 0; i < size; i++)
1915 AlignmentPanel ap = af.alignPanels.get(i);
1916 AlignFrame newaf = new AlignFrame(ap);
1919 * Restore the view's last exploded frame geometry if known. Multiple
1920 * views from one exploded frame share and restore the same (frame)
1921 * position and size.
1923 Rectangle geometry = ap.av.getExplodedGeometry();
1924 if (geometry != null)
1926 newaf.setBounds(geometry);
1929 ap.av.setGatherViewsHere(false);
1931 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1932 AlignFrame.DEFAULT_HEIGHT);
1935 af.alignPanels.clear();
1936 af.closeMenuItem_actionPerformed(true);
1941 * Gather expanded views (separate AlignFrame's) with the same sequence set
1942 * identifier back in to this frame as additional views, and close the
1943 * expanded views. Note the expanded frames may themselves have multiple
1944 * views. We take the lot.
1948 public void gatherViews(AlignFrame source)
1950 source.viewport.setGatherViewsHere(true);
1951 source.viewport.setExplodedGeometry(source.getBounds());
1952 JInternalFrame[] frames = desktop.getAllFrames();
1953 String viewId = source.viewport.getSequenceSetId();
1955 for (int t = 0; t < frames.length; t++)
1957 if (frames[t] instanceof AlignFrame && frames[t] != source)
1959 AlignFrame af = (AlignFrame) frames[t];
1960 boolean gatherThis = false;
1961 for (int a = 0; a < af.alignPanels.size(); a++)
1963 AlignmentPanel ap = af.alignPanels.get(a);
1964 if (viewId.equals(ap.av.getSequenceSetId()))
1967 ap.av.setGatherViewsHere(false);
1968 ap.av.setExplodedGeometry(af.getBounds());
1969 source.addAlignmentPanel(ap, false);
1975 af.alignPanels.clear();
1976 af.closeMenuItem_actionPerformed(true);
1983 jalview.gui.VamsasApplication v_client = null;
1986 public void vamsasImport_actionPerformed(ActionEvent e)
1988 if (v_client == null)
1990 // Load and try to start a session.
1991 JalviewFileChooser chooser = new JalviewFileChooser(
1992 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1994 chooser.setFileView(new JalviewFileView());
1995 chooser.setDialogTitle(
1996 MessageManager.getString("label.open_saved_vamsas_session"));
1997 chooser.setToolTipText(MessageManager.getString(
1998 "label.select_vamsas_session_opened_as_new_vamsas_session"));
2000 int value = chooser.showOpenDialog(this);
2002 if (value == JalviewFileChooser.APPROVE_OPTION)
2004 String fle = chooser.getSelectedFile().toString();
2005 if (!vamsasImport(chooser.getSelectedFile()))
2007 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2008 MessageManager.formatMessage(
2009 "label.couldnt_import_as_vamsas_session",
2013 .getString("label.vamsas_document_import_failed"),
2014 JvOptionPane.ERROR_MESSAGE);
2020 jalview.bin.Cache.log.error(
2021 "Implementation error - load session from a running session is not supported.");
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(URL url)
2033 // TODO: create progress bar
2034 if (v_client != null)
2037 jalview.bin.Cache.log.error(
2038 "Implementation error - load session from a running session is not supported.");
2044 // copy the URL content to a temporary local file
2045 // TODO: be a bit cleverer here with nio (?!)
2046 File file = File.createTempFile("vdocfromurl", ".vdj");
2047 FileOutputStream fos = new FileOutputStream(file);
2048 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2049 byte[] buffer = new byte[2048];
2051 while ((ln = bis.read(buffer)) > -1)
2053 fos.write(buffer, 0, ln);
2057 v_client = new jalview.gui.VamsasApplication(this, file,
2058 url.toExternalForm());
2059 } catch (Exception ex)
2061 jalview.bin.Cache.log.error(
2062 "Failed to create new vamsas session from contents of URL "
2067 setupVamsasConnectedGui();
2068 v_client.initial_update(); // TODO: thread ?
2069 return v_client.inSession();
2073 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2076 * @return true if import was a success and a session was started.
2078 public boolean vamsasImport(File file)
2080 if (v_client != null)
2083 jalview.bin.Cache.log.error(
2084 "Implementation error - load session from a running session is not supported.");
2088 setProgressBar(MessageManager.formatMessage(
2089 "status.importing_vamsas_session_from", new Object[]
2090 { file.getName() }), file.hashCode());
2093 v_client = new jalview.gui.VamsasApplication(this, file, null);
2094 } catch (Exception ex)
2096 setProgressBar(MessageManager.formatMessage(
2097 "status.importing_vamsas_session_from", new Object[]
2098 { file.getName() }), file.hashCode());
2099 jalview.bin.Cache.log.error(
2100 "New vamsas session from existing session file failed:", ex);
2103 setupVamsasConnectedGui();
2104 v_client.initial_update(); // TODO: thread ?
2105 setProgressBar(MessageManager.formatMessage(
2106 "status.importing_vamsas_session_from", new Object[]
2107 { file.getName() }), file.hashCode());
2108 return v_client.inSession();
2111 public boolean joinVamsasSession(String mysesid)
2113 if (v_client != null)
2115 throw new Error(MessageManager
2116 .getString("error.try_join_vamsas_session_another"));
2118 if (mysesid == null)
2121 MessageManager.getString("error.invalid_vamsas_session_id"));
2123 v_client = new VamsasApplication(this, mysesid);
2124 setupVamsasConnectedGui();
2125 v_client.initial_update();
2126 return (v_client.inSession());
2130 public void vamsasStart_actionPerformed(ActionEvent e)
2132 if (v_client == null)
2135 // we just start a default session for moment.
2137 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2138 * getProperty("LAST_DIRECTORY"));
2140 * chooser.setFileView(new JalviewFileView());
2141 * chooser.setDialogTitle("Load Vamsas file");
2142 * chooser.setToolTipText("Import");
2144 * int value = chooser.showOpenDialog(this);
2146 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2147 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2149 v_client = new VamsasApplication(this);
2150 setupVamsasConnectedGui();
2151 v_client.initial_update(); // TODO: thread ?
2155 // store current data in session.
2156 v_client.push_update(); // TODO: thread
2160 protected void setupVamsasConnectedGui()
2162 vamsasStart.setText(MessageManager.getString("label.session_update"));
2163 vamsasSave.setVisible(true);
2164 vamsasStop.setVisible(true);
2165 vamsasImport.setVisible(false); // Document import to existing session is
2166 // not possible for vamsas-client-1.0.
2169 protected void setupVamsasDisconnectedGui()
2171 vamsasSave.setVisible(false);
2172 vamsasStop.setVisible(false);
2173 vamsasImport.setVisible(true);
2175 .setText(MessageManager.getString("label.new_vamsas_session"));
2179 public void vamsasStop_actionPerformed(ActionEvent e)
2181 if (v_client != null)
2183 v_client.end_session();
2185 setupVamsasDisconnectedGui();
2189 protected void buildVamsasStMenu()
2191 if (v_client == null)
2193 String[] sess = null;
2196 sess = VamsasApplication.getSessionList();
2197 } catch (Exception e)
2199 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2205 jalview.bin.Cache.log.debug(
2206 "Got current sessions list: " + sess.length + " entries.");
2207 VamsasStMenu.removeAll();
2208 for (int i = 0; i < sess.length; i++)
2210 JMenuItem sessit = new JMenuItem();
2211 sessit.setText(sess[i]);
2212 sessit.setToolTipText(MessageManager
2213 .formatMessage("label.connect_to_session", new Object[]
2215 final Desktop dsktp = this;
2216 final String mysesid = sess[i];
2217 sessit.addActionListener(new ActionListener()
2221 public void actionPerformed(ActionEvent e)
2223 if (dsktp.v_client == null)
2225 Thread rthr = new Thread(new Runnable()
2231 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2232 dsktp.setupVamsasConnectedGui();
2233 dsktp.v_client.initial_update();
2241 VamsasStMenu.add(sessit);
2243 // don't show an empty menu.
2244 VamsasStMenu.setVisible(sess.length > 0);
2249 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2250 VamsasStMenu.removeAll();
2251 VamsasStMenu.setVisible(false);
2256 // Not interested in the content. Just hide ourselves.
2257 VamsasStMenu.setVisible(false);
2262 public void vamsasSave_actionPerformed(ActionEvent e)
2264 if (v_client != null)
2266 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2267 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2270 chooser.setFileView(new JalviewFileView());
2271 chooser.setDialogTitle(MessageManager
2272 .getString("label.save_vamsas_document_archive"));
2274 int value = chooser.showSaveDialog(this);
2276 if (value == JalviewFileChooser.APPROVE_OPTION)
2278 java.io.File choice = chooser.getSelectedFile();
2279 JPanel progpanel = addProgressPanel(MessageManager
2280 .formatMessage("label.saving_vamsas_doc", new Object[]
2281 { choice.getName() }));
2282 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2283 String warnmsg = null;
2284 String warnttl = null;
2287 v_client.vclient.storeDocument(choice);
2290 warnttl = "Serious Problem saving Vamsas Document";
2291 warnmsg = ex.toString();
2292 jalview.bin.Cache.log
2293 .error("Error Whilst saving document to " + choice, ex);
2295 } catch (Exception ex)
2297 warnttl = "Problem saving Vamsas Document.";
2298 warnmsg = ex.toString();
2299 jalview.bin.Cache.log.warn(
2300 "Exception Whilst saving document to " + choice, ex);
2303 removeProgressPanel(progpanel);
2304 if (warnmsg != null)
2306 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2308 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2314 JPanel vamUpdate = null;
2317 * hide vamsas user gui bits when a vamsas document event is being handled.
2320 * true to hide gui, false to reveal gui
2322 public void setVamsasUpdate(boolean b)
2324 Cache.log.debug("Setting gui for Vamsas update "
2325 + (b ? "in progress" : "finished"));
2327 if (vamUpdate != null)
2329 this.removeProgressPanel(vamUpdate);
2333 vamUpdate = this.addProgressPanel(
2334 MessageManager.getString("label.updating_vamsas_session"));
2336 vamsasStart.setVisible(!b);
2337 vamsasStop.setVisible(!b);
2338 vamsasSave.setVisible(!b);
2341 public JInternalFrame[] getAllFrames()
2343 return desktop.getAllFrames();
2347 * Checks the given url to see if it gives a response indicating that the user
2348 * should be informed of a new questionnaire.
2352 public void checkForQuestionnaire(String url)
2354 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2355 // javax.swing.SwingUtilities.invokeLater(jvq);
2356 new Thread(jvq).start();
2359 public void checkURLLinks()
2361 // Thread off the URL link checker
2362 addDialogThread(new Runnable()
2367 if (Cache.getDefault("CHECKURLLINKS", true))
2369 // check what the actual links are - if it's just the default don't
2370 // bother with the warning
2371 List<String> links = Preferences.sequenceUrlLinks
2374 // only need to check links if there is one with a
2375 // SEQUENCE_ID which is not the default EMBL_EBI link
2376 ListIterator<String> li = links.listIterator();
2377 boolean check = false;
2378 List<JLabel> urls = new ArrayList<>();
2379 while (li.hasNext())
2381 String link = li.next();
2382 if (link.contains(SEQUENCE_ID)
2383 && !UrlConstants.isDefaultString(link))
2386 int barPos = link.indexOf("|");
2387 String urlMsg = barPos == -1 ? link
2388 : link.substring(0, barPos) + ": "
2389 + link.substring(barPos + 1);
2390 urls.add(new JLabel(urlMsg));
2398 // ask user to check in case URL links use old style tokens
2399 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2400 JPanel msgPanel = new JPanel();
2401 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2402 msgPanel.add(Box.createVerticalGlue());
2403 JLabel msg = new JLabel(MessageManager
2404 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2405 JLabel msg2 = new JLabel(MessageManager
2406 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2408 for (JLabel url : urls)
2414 final JCheckBox jcb = new JCheckBox(
2415 MessageManager.getString("label.do_not_display_again"));
2416 jcb.addActionListener(new ActionListener()
2419 public void actionPerformed(ActionEvent e)
2421 // update Cache settings for "don't show this again"
2422 boolean showWarningAgain = !jcb.isSelected();
2423 Cache.setProperty("CHECKURLLINKS",
2424 Boolean.valueOf(showWarningAgain).toString());
2429 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2431 .getString("label.SEQUENCE_ID_no_longer_used"),
2432 JvOptionPane.WARNING_MESSAGE);
2439 * Proxy class for JDesktopPane which optionally displays the current memory
2440 * usage and highlights the desktop area with a red bar if free memory runs
2445 public class MyDesktopPane extends JDesktopPane implements Runnable
2448 private static final float ONE_MB = 1048576f;
2450 boolean showMemoryUsage = false;
2454 java.text.NumberFormat df;
2456 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2459 public MyDesktopPane(boolean showMemoryUsage)
2461 showMemoryUsage(showMemoryUsage);
2464 public void showMemoryUsage(boolean showMemory)
2466 this.showMemoryUsage = showMemory;
2469 Thread worker = new Thread(this);
2475 public boolean isShowMemoryUsage()
2477 return showMemoryUsage;
2483 df = java.text.NumberFormat.getNumberInstance();
2484 df.setMaximumFractionDigits(2);
2485 runtime = Runtime.getRuntime();
2487 while (showMemoryUsage)
2491 maxMemory = runtime.maxMemory() / ONE_MB;
2492 allocatedMemory = runtime.totalMemory() / ONE_MB;
2493 freeMemory = runtime.freeMemory() / ONE_MB;
2494 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2496 percentUsage = (totalFreeMemory / maxMemory) * 100;
2498 // if (percentUsage < 20)
2500 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2502 // instance.set.setBorder(border1);
2505 // sleep after showing usage
2507 } catch (Exception ex)
2509 ex.printStackTrace();
2515 public void paintComponent(Graphics g)
2517 if (showMemoryUsage && g != null && df != null)
2519 if (percentUsage < 20)
2521 g.setColor(Color.red);
2523 FontMetrics fm = g.getFontMetrics();
2526 g.drawString(MessageManager.formatMessage("label.memory_stats",
2528 { df.format(totalFreeMemory), df.format(maxMemory),
2529 df.format(percentUsage) }),
2530 10, getHeight() - fm.getHeight());
2538 * Accessor method to quickly get all the AlignmentFrames loaded.
2540 * @return an array of AlignFrame, or null if none found
2542 public static AlignFrame[] getAlignFrames()
2544 if (Jalview.isHeadlessMode())
2546 // Desktop.desktop is null in headless mode
2547 return new AlignFrame[] { Jalview.currentAlignFrame };
2550 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2556 List<AlignFrame> avp = new ArrayList<>();
2558 for (int i = frames.length - 1; i > -1; i--)
2560 if (frames[i] instanceof AlignFrame)
2562 avp.add((AlignFrame) frames[i]);
2564 else if (frames[i] instanceof SplitFrame)
2567 * Also check for a split frame containing an AlignFrame
2569 GSplitFrame sf = (GSplitFrame) frames[i];
2570 if (sf.getTopFrame() instanceof AlignFrame)
2572 avp.add((AlignFrame) sf.getTopFrame());
2574 if (sf.getBottomFrame() instanceof AlignFrame)
2576 avp.add((AlignFrame) sf.getBottomFrame());
2580 if (avp.size() == 0)
2584 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2589 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2593 public GStructureViewer[] getJmols()
2595 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2601 List<GStructureViewer> avp = new ArrayList<>();
2603 for (int i = frames.length - 1; i > -1; i--)
2605 if (frames[i] instanceof AppJmol)
2607 GStructureViewer af = (GStructureViewer) frames[i];
2611 if (avp.size() == 0)
2615 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2620 * Add Groovy Support to Jalview
2623 public void groovyShell_actionPerformed()
2627 openGroovyConsole();
2628 } catch (Exception ex)
2630 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2631 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2633 MessageManager.getString("label.couldnt_create_groovy_shell"),
2634 MessageManager.getString("label.groovy_support_failed"),
2635 JvOptionPane.ERROR_MESSAGE);
2640 * Open the Groovy console
2642 void openGroovyConsole()
2644 if (groovyConsole == null)
2646 groovyConsole = new groovy.ui.Console();
2647 groovyConsole.setVariable("Jalview", this);
2648 groovyConsole.run();
2651 * We allow only one console at a time, so that AlignFrame menu option
2652 * 'Calculate | Run Groovy script' is unambiguous.
2653 * Disable 'Groovy Console', and enable 'Run script', when the console is
2654 * opened, and the reverse when it is closed
2656 Window window = (Window) groovyConsole.getFrame();
2657 window.addWindowListener(new WindowAdapter()
2660 public void windowClosed(WindowEvent e)
2663 * rebind CMD-Q from Groovy Console to Jalview Quit
2666 enableExecuteGroovy(false);
2672 * show Groovy console window (after close and reopen)
2674 ((Window) groovyConsole.getFrame()).setVisible(true);
2677 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2678 * and disable opening a second console
2680 enableExecuteGroovy(true);
2684 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2685 * binding when opened
2687 protected void addQuitHandler()
2689 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2690 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2691 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2693 getRootPane().getActionMap().put("Quit", new AbstractAction()
2696 public void actionPerformed(ActionEvent e)
2704 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2707 * true if Groovy console is open
2709 public void enableExecuteGroovy(boolean enabled)
2712 * disable opening a second Groovy console
2713 * (or re-enable when the console is closed)
2715 groovyShell.setEnabled(!enabled);
2717 AlignFrame[] alignFrames = getAlignFrames();
2718 if (alignFrames != null)
2720 for (AlignFrame af : alignFrames)
2722 af.setGroovyEnabled(enabled);
2728 * Progress bars managed by the IProgressIndicator method.
2730 private Hashtable<Long, JPanel> progressBars;
2732 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2737 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2740 public void setProgressBar(String message, long id)
2742 if (progressBars == null)
2744 progressBars = new Hashtable<>();
2745 progressBarHandlers = new Hashtable<>();
2748 if (progressBars.get(new Long(id)) != null)
2750 JPanel panel = progressBars.remove(new Long(id));
2751 if (progressBarHandlers.contains(new Long(id)))
2753 progressBarHandlers.remove(new Long(id));
2755 removeProgressPanel(panel);
2759 progressBars.put(new Long(id), addProgressPanel(message));
2766 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2767 * jalview.gui.IProgressIndicatorHandler)
2770 public void registerHandler(final long id,
2771 final IProgressIndicatorHandler handler)
2773 if (progressBarHandlers == null
2774 || !progressBars.containsKey(new Long(id)))
2776 throw new Error(MessageManager.getString(
2777 "error.call_setprogressbar_before_registering_handler"));
2779 progressBarHandlers.put(new Long(id), handler);
2780 final JPanel progressPanel = progressBars.get(new Long(id));
2781 if (handler.canCancel())
2783 JButton cancel = new JButton(
2784 MessageManager.getString("action.cancel"));
2785 final IProgressIndicator us = this;
2786 cancel.addActionListener(new ActionListener()
2790 public void actionPerformed(ActionEvent e)
2792 handler.cancelActivity(id);
2793 us.setProgressBar(MessageManager
2794 .formatMessage("label.cancelled_params", new Object[]
2795 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2799 progressPanel.add(cancel, BorderLayout.EAST);
2805 * @return true if any progress bars are still active
2808 public boolean operationInProgress()
2810 if (progressBars != null && progressBars.size() > 0)
2818 * This will return the first AlignFrame holding the given viewport instance.
2819 * It will break if there are more than one AlignFrames viewing a particular
2823 * @return alignFrame for viewport
2825 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2827 if (desktop != null)
2829 AlignmentPanel[] aps = getAlignmentPanels(
2830 viewport.getSequenceSetId());
2831 for (int panel = 0; aps != null && panel < aps.length; panel++)
2833 if (aps[panel] != null && aps[panel].av == viewport)
2835 return aps[panel].alignFrame;
2842 public VamsasApplication getVamsasApplication()
2849 * flag set if jalview GUI is being operated programmatically
2851 private boolean inBatchMode = false;
2854 * check if jalview GUI is being operated programmatically
2856 * @return inBatchMode
2858 public boolean isInBatchMode()
2864 * set flag if jalview GUI is being operated programmatically
2866 * @param inBatchMode
2868 public void setInBatchMode(boolean inBatchMode)
2870 this.inBatchMode = inBatchMode;
2873 public void startServiceDiscovery()
2875 startServiceDiscovery(false);
2878 public void startServiceDiscovery(boolean blocking)
2880 boolean alive = true;
2881 Thread t0 = null, t1 = null, t2 = null;
2882 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2885 // todo: changesupport handlers need to be transferred
2886 if (discoverer == null)
2888 discoverer = new jalview.ws.jws1.Discoverer();
2889 // register PCS handler for desktop.
2890 discoverer.addPropertyChangeListener(changeSupport);
2892 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2893 // until we phase out completely
2894 (t0 = new Thread(discoverer)).start();
2897 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2899 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2900 .startDiscoverer(changeSupport);
2904 // TODO: do rest service discovery
2913 } catch (Exception e)
2916 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2917 || (t3 != null && t3.isAlive())
2918 || (t0 != null && t0.isAlive());
2924 * called to check if the service discovery process completed successfully.
2928 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2930 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2932 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2933 .getErrorMessages();
2936 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2938 if (serviceChangedDialog == null)
2940 // only run if we aren't already displaying one of these.
2941 addDialogThread(serviceChangedDialog = new Runnable()
2948 * JalviewDialog jd =new JalviewDialog() {
2950 * @Override protected void cancelPressed() { // TODO
2951 * Auto-generated method stub
2953 * }@Override protected void okPressed() { // TODO
2954 * Auto-generated method stub
2956 * }@Override protected void raiseClosed() { // TODO
2957 * Auto-generated method stub
2959 * } }; jd.initDialogFrame(new
2960 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2961 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2962 * + " or mis-configured HTTP proxy settings.<br/>" +
2963 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2965 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2966 * ), true, true, "Web Service Configuration Problem", 450,
2969 * jd.waitForInput();
2971 JvOptionPane.showConfirmDialog(Desktop.desktop,
2972 new JLabel("<html><table width=\"450\"><tr><td>"
2973 + ermsg + "</td></tr></table>"
2974 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2975 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2976 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2977 + " Tools->Preferences dialog box to change them.</p></html>"),
2978 "Web Service Configuration Problem",
2979 JvOptionPane.DEFAULT_OPTION,
2980 JvOptionPane.ERROR_MESSAGE);
2981 serviceChangedDialog = null;
2990 "Errors reported by JABA discovery service. Check web services preferences.\n"
2997 private Runnable serviceChangedDialog = null;
3000 * start a thread to open a URL in the configured browser. Pops up a warning
3001 * dialog to the user if there is an exception when calling out to the browser
3006 public static void showUrl(final String url)
3008 showUrl(url, Desktop.instance);
3012 * Like showUrl but allows progress handler to be specified
3016 * (null) or object implementing IProgressIndicator
3018 public static void showUrl(final String url,
3019 final IProgressIndicator progress)
3021 new Thread(new Runnable()
3028 if (progress != null)
3030 progress.setProgressBar(MessageManager
3031 .formatMessage("status.opening_params", new Object[]
3032 { url }), this.hashCode());
3034 jalview.util.BrowserLauncher.openURL(url);
3035 } catch (Exception ex)
3037 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3039 .getString("label.web_browser_not_found_unix"),
3040 MessageManager.getString("label.web_browser_not_found"),
3041 JvOptionPane.WARNING_MESSAGE);
3043 ex.printStackTrace();
3045 if (progress != null)
3047 progress.setProgressBar(null, this.hashCode());
3053 public static WsParamSetManager wsparamManager = null;
3055 public static ParamManager getUserParameterStore()
3057 if (wsparamManager == null)
3059 wsparamManager = new WsParamSetManager();
3061 return wsparamManager;
3065 * static hyperlink handler proxy method for use by Jalview's internal windows
3069 public static void hyperlinkUpdate(HyperlinkEvent e)
3071 if (e.getEventType() == EventType.ACTIVATED)
3076 url = e.getURL().toString();
3077 Desktop.showUrl(url);
3078 } catch (Exception x)
3082 if (Cache.log != null)
3084 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3089 "Couldn't handle string " + url + " as a URL.");
3092 // ignore any exceptions due to dud links.
3099 * single thread that handles display of dialogs to user.
3101 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3104 * flag indicating if dialogExecutor should try to acquire a permit
3106 private volatile boolean dialogPause = true;
3111 private java.util.concurrent.Semaphore block = new Semaphore(0);
3113 private static groovy.ui.Console groovyConsole;
3116 * add another dialog thread to the queue
3120 public void addDialogThread(final Runnable prompter)
3122 dialogExecutor.submit(new Runnable()
3132 } catch (InterruptedException x)
3137 if (instance == null)
3143 SwingUtilities.invokeAndWait(prompter);
3144 } catch (Exception q)
3146 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3152 public void startDialogQueue()
3154 // set the flag so we don't pause waiting for another permit and semaphore
3155 // the current task to begin
3156 dialogPause = false;
3161 protected void snapShotWindow_actionPerformed(ActionEvent e)
3165 ImageMaker im = new jalview.util.ImageMaker(
3166 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3167 getHeight(), of = new File("Jalview_snapshot"
3168 + System.currentTimeMillis() + ".eps"),
3169 "View of desktop", null, 0, false);
3172 paintAll(im.getGraphics());
3174 } catch (Exception q)
3176 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3180 Cache.log.info("Successfully written snapshot to file "
3181 + of.getAbsolutePath());
3185 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3186 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3187 * and location last time the view was expanded (if any). However it does not
3188 * remember the split pane divider location - this is set to match the
3189 * 'exploding' frame.
3193 public void explodeViews(SplitFrame sf)
3195 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3196 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3197 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3199 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3201 int viewCount = topPanels.size();
3208 * Processing in reverse order works, forwards order leaves the first panels
3209 * not visible. I don't know why!
3211 for (int i = viewCount - 1; i >= 0; i--)
3214 * Make new top and bottom frames. These take over the respective
3215 * AlignmentPanel objects, including their AlignmentViewports, so the
3216 * cdna/protein relationships between the viewports is carried over to the
3219 * explodedGeometry holds the (x, y) position of the previously exploded
3220 * SplitFrame, and the (width, height) of the AlignFrame component
3222 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3223 AlignFrame newTopFrame = new AlignFrame(topPanel);
3224 newTopFrame.setSize(oldTopFrame.getSize());
3225 newTopFrame.setVisible(true);
3226 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3227 .getExplodedGeometry();
3228 if (geometry != null)
3230 newTopFrame.setSize(geometry.getSize());
3233 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3234 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3235 newBottomFrame.setSize(oldBottomFrame.getSize());
3236 newBottomFrame.setVisible(true);
3237 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3238 .getExplodedGeometry();
3239 if (geometry != null)
3241 newBottomFrame.setSize(geometry.getSize());
3244 topPanel.av.setGatherViewsHere(false);
3245 bottomPanel.av.setGatherViewsHere(false);
3246 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3248 if (geometry != null)
3250 splitFrame.setLocation(geometry.getLocation());
3252 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3256 * Clear references to the panels (now relocated in the new SplitFrames)
3257 * before closing the old SplitFrame.
3260 bottomPanels.clear();
3265 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3266 * back into the given SplitFrame as additional views. Note that the gathered
3267 * frames may themselves have multiple views.
3271 public void gatherViews(GSplitFrame source)
3274 * special handling of explodedGeometry for a view within a SplitFrame: - it
3275 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3276 * height) of the AlignFrame component
3278 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3279 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3280 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3281 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3282 myBottomFrame.viewport
3283 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3284 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3285 myTopFrame.viewport.setGatherViewsHere(true);
3286 myBottomFrame.viewport.setGatherViewsHere(true);
3287 String topViewId = myTopFrame.viewport.getSequenceSetId();
3288 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3290 JInternalFrame[] frames = desktop.getAllFrames();
3291 for (JInternalFrame frame : frames)
3293 if (frame instanceof SplitFrame && frame != source)
3295 SplitFrame sf = (SplitFrame) frame;
3296 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3297 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3298 boolean gatherThis = false;
3299 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3301 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3302 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3303 if (topViewId.equals(topPanel.av.getSequenceSetId())
3304 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3307 topPanel.av.setGatherViewsHere(false);
3308 bottomPanel.av.setGatherViewsHere(false);
3309 topPanel.av.setExplodedGeometry(
3310 new Rectangle(sf.getLocation(), topFrame.getSize()));
3311 bottomPanel.av.setExplodedGeometry(
3312 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3313 myTopFrame.addAlignmentPanel(topPanel, false);
3314 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3320 topFrame.getAlignPanels().clear();
3321 bottomFrame.getAlignPanels().clear();
3328 * The dust settles...give focus to the tab we did this from.
3330 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3333 public static groovy.ui.Console getGroovyConsole()
3335 return groovyConsole;
3338 public static void transferFromDropTarget(List<String> files,
3339 List<DataSourceType> protocols, DropTargetDropEvent evt,
3340 Transferable t) throws Exception
3343 DataFlavor uriListFlavor = new DataFlavor(
3344 "text/uri-list;class=java.lang.String");
3345 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3347 // Works on Windows and MacOSX
3348 Cache.log.debug("Drop handled as javaFileListFlavor");
3349 for (Object file : (List) t
3350 .getTransferData(DataFlavor.javaFileListFlavor))
3352 files.add(((File) file).toString());
3353 protocols.add(DataSourceType.FILE);
3358 // Unix like behaviour
3359 boolean added = false;
3361 if (t.isDataFlavorSupported(uriListFlavor))
3363 Cache.log.debug("Drop handled as uriListFlavor");
3364 // This is used by Unix drag system
3365 data = (String) t.getTransferData(uriListFlavor);
3369 // fallback to text: workaround - on OSX where there's a JVM bug
3370 Cache.log.debug("standard URIListFlavor failed. Trying text");
3371 // try text fallback
3372 data = (String) t.getTransferData(
3373 new DataFlavor("text/plain;class=java.lang.String"));
3374 if (Cache.log.isDebugEnabled())
3376 Cache.log.debug("fallback returned " + data);
3379 while (protocols.size() < files.size())
3381 Cache.log.debug("Adding missing FILE protocol for "
3382 + files.get(protocols.size()));
3383 protocols.add(DataSourceType.FILE);
3385 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3386 data, "\r\n"); st.hasMoreTokens();)
3389 String s = st.nextToken();
3390 if (s.startsWith("#"))
3392 // the line is a comment (as per the RFC 2483)
3395 java.net.URI uri = new java.net.URI(s);
3396 if (uri.getScheme().toLowerCase().startsWith("http"))
3398 protocols.add(DataSourceType.URL);
3399 files.add(uri.toString());
3403 // otherwise preserve old behaviour: catch all for file objects
3404 java.io.File file = new java.io.File(uri);
3405 protocols.add(DataSourceType.FILE);
3406 files.add(file.toString());
3409 if (Cache.log.isDebugEnabled())
3411 if (data == null || !added)
3414 "Couldn't resolve drop data. Here are the supported flavors:");
3415 for (DataFlavor fl : t.getTransferDataFlavors())
3418 "Supported transfer dataflavor: " + fl.toString());
3419 Object df = t.getTransferData(fl);
3422 Cache.log.debug("Retrieves: " + df);
3426 Cache.log.debug("Retrieved nothing");
3435 * Sets the Preferences property for experimental features to True or False
3436 * depending on the state of the controlling menu item
3439 protected void showExperimental_actionPerformed(boolean selected)
3441 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));