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.FormatAdapter;
36 import jalview.io.IdentifyFile;
37 import jalview.io.JalviewFileChooser;
38 import jalview.io.JalviewFileView;
39 import jalview.jbgui.GSplitFrame;
40 import jalview.jbgui.GStructureViewer;
41 import jalview.structure.StructureSelectionManager;
42 import jalview.urls.IdOrgSettings;
43 import jalview.util.ImageMaker;
44 import jalview.util.MessageManager;
45 import jalview.util.Platform;
46 import jalview.util.UrlConstants;
47 import jalview.viewmodel.AlignmentViewport;
48 import jalview.ws.params.ParamManager;
49 import jalview.ws.utils.UrlDownloadClient;
51 import java.awt.BorderLayout;
52 import java.awt.Color;
53 import java.awt.Dimension;
54 import java.awt.FontMetrics;
55 import java.awt.Graphics;
56 import java.awt.GridLayout;
57 import java.awt.Point;
58 import java.awt.Rectangle;
59 import java.awt.Toolkit;
60 import java.awt.Window;
61 import java.awt.datatransfer.Clipboard;
62 import java.awt.datatransfer.ClipboardOwner;
63 import java.awt.datatransfer.DataFlavor;
64 import java.awt.datatransfer.Transferable;
65 import java.awt.dnd.DnDConstants;
66 import java.awt.dnd.DropTargetDragEvent;
67 import java.awt.dnd.DropTargetDropEvent;
68 import java.awt.dnd.DropTargetEvent;
69 import java.awt.dnd.DropTargetListener;
70 import java.awt.event.ActionEvent;
71 import java.awt.event.ActionListener;
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;
120 import org.stackoverflowusers.file.WindowsShortcut;
127 * @version $Revision: 1.155 $
129 public class Desktop extends jalview.jbgui.GDesktop
130 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
131 jalview.api.StructureSelectionManagerProvider
133 private static int DEFAULT_MIN_WIDTH = 300;
135 private static int DEFAULT_MIN_HEIGHT = 250;
137 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
139 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
141 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
143 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
146 * news reader - null if it was never started.
148 private BlogReader jvnews = null;
150 private File projectFile;
154 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
156 public void addJalviewPropertyChangeListener(
157 PropertyChangeListener listener)
159 changeSupport.addJalviewPropertyChangeListener(listener);
163 * @param propertyName
165 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
166 * java.beans.PropertyChangeListener)
168 public void addJalviewPropertyChangeListener(String propertyName,
169 PropertyChangeListener listener)
171 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
175 * @param propertyName
177 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
178 * java.beans.PropertyChangeListener)
180 public void removeJalviewPropertyChangeListener(String propertyName,
181 PropertyChangeListener listener)
183 changeSupport.removeJalviewPropertyChangeListener(propertyName,
187 /** Singleton Desktop instance */
188 public static Desktop instance;
190 public static MyDesktopPane desktop;
192 static int openFrameCount = 0;
194 static final int xOffset = 30;
196 static final int yOffset = 30;
198 public static jalview.ws.jws1.Discoverer discoverer;
200 public static Object[] jalviewClipboard;
202 public static boolean internalCopy = false;
204 static int fileLoadingCount = 0;
206 class MyDesktopManager implements DesktopManager
209 private DesktopManager delegate;
211 public MyDesktopManager(DesktopManager delegate)
213 this.delegate = delegate;
217 public void activateFrame(JInternalFrame f)
221 delegate.activateFrame(f);
222 } catch (NullPointerException npe)
224 Point p = getMousePosition();
225 instance.showPasteMenu(p.x, p.y);
230 public void beginDraggingFrame(JComponent f)
232 delegate.beginDraggingFrame(f);
236 public void beginResizingFrame(JComponent f, int direction)
238 delegate.beginResizingFrame(f, direction);
242 public void closeFrame(JInternalFrame f)
244 delegate.closeFrame(f);
248 public void deactivateFrame(JInternalFrame f)
250 delegate.deactivateFrame(f);
254 public void deiconifyFrame(JInternalFrame f)
256 delegate.deiconifyFrame(f);
260 public void dragFrame(JComponent f, int newX, int newY)
266 delegate.dragFrame(f, newX, newY);
270 public void endDraggingFrame(JComponent f)
272 delegate.endDraggingFrame(f);
277 public void endResizingFrame(JComponent f)
279 delegate.endResizingFrame(f);
284 public void iconifyFrame(JInternalFrame f)
286 delegate.iconifyFrame(f);
290 public void maximizeFrame(JInternalFrame f)
292 delegate.maximizeFrame(f);
296 public void minimizeFrame(JInternalFrame f)
298 delegate.minimizeFrame(f);
302 public void openFrame(JInternalFrame f)
304 delegate.openFrame(f);
308 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
315 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
319 public void setBoundsForFrame(JComponent f, int newX, int newY,
320 int newWidth, int newHeight)
322 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
325 // All other methods, simply delegate
330 * Creates a new Desktop object.
335 * A note to implementors. It is ESSENTIAL that any activities that might
336 * block are spawned off as threads rather than waited for during this
340 doVamsasClientCheck();
342 doConfigureStructurePrefs();
343 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
344 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
345 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
347 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
349 desktop = new MyDesktopPane(selmemusage);
350 showMemusage.setSelected(selmemusage);
351 desktop.setBackground(Color.white);
352 getContentPane().setLayout(new BorderLayout());
353 // alternate config - have scrollbars - see notes in JAL-153
354 // JScrollPane sp = new JScrollPane();
355 // sp.getViewport().setView(desktop);
356 // getContentPane().add(sp, BorderLayout.CENTER);
357 getContentPane().add(desktop, BorderLayout.CENTER);
358 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
360 // This line prevents Windows Look&Feel resizing all new windows to maximum
361 // if previous window was maximised
362 desktop.setDesktopManager(
363 new MyDesktopManager(
364 (Platform.isWindows() ? new DefaultDesktopManager()
366 ? new AquaInternalFrameManager(
367 desktop.getDesktopManager())
368 : desktop.getDesktopManager())));
370 Rectangle dims = getLastKnownDimensions("");
377 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
378 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
381 jconsole = new Console(this, showjconsole);
382 // add essential build information
384 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
385 + "\n" + "Jalview Installation: "
386 + jalview.bin.Cache.getDefault("INSTALLATION",
388 + "\n" + "Build Date: "
389 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
390 + "\n" + "Java version: "
391 + System.getProperty("java.version") + "\n"
392 + System.getProperty("os.arch") + " "
393 + System.getProperty("os.name") + " "
394 + System.getProperty("os.version"));
396 showConsole(showjconsole);
398 showNews.setVisible(false);
400 experimentalFeatures.setSelected(showExperimental());
402 getIdentifiersOrgData();
406 this.addWindowListener(new WindowAdapter()
409 public void windowClosing(WindowEvent evt)
416 this.addMouseListener(ma = new MouseAdapter()
419 public void mousePressed(MouseEvent evt)
421 if (evt.isPopupTrigger()) // Mac
423 showPasteMenu(evt.getX(), evt.getY());
428 public void mouseReleased(MouseEvent evt)
430 if (evt.isPopupTrigger()) // Windows
432 showPasteMenu(evt.getX(), evt.getY());
436 desktop.addMouseListener(ma);
438 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
439 // Spawn a thread that shows the splashscreen
440 SwingUtilities.invokeLater(new Runnable()
449 // Thread off a new instance of the file chooser - this reduces the time it
450 // takes to open it later on.
451 new Thread(new Runnable()
456 Cache.log.debug("Filechooser init thread started.");
457 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
458 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
460 Cache.log.debug("Filechooser init thread finished.");
463 // Add the service change listener
464 changeSupport.addJalviewPropertyChangeListener("services",
465 new PropertyChangeListener()
469 public void propertyChange(PropertyChangeEvent evt)
471 Cache.log.debug("Firing service changed event for "
472 + evt.getNewValue());
473 JalviewServicesChanged(evt);
480 * Answers true if user preferences to enable experimental features is True
485 public boolean showExperimental()
487 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
488 Boolean.FALSE.toString());
489 return Boolean.valueOf(experimental).booleanValue();
492 public void doConfigureStructurePrefs()
494 // configure services
495 StructureSelectionManager ssm = StructureSelectionManager
496 .getStructureSelectionManager(this);
497 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
499 ssm.setAddTempFacAnnot(jalview.bin.Cache
500 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
501 ssm.setProcessSecondaryStructure(jalview.bin.Cache
502 .getDefault(Preferences.STRUCT_FROM_PDB, true));
503 ssm.setSecStructServices(
504 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
508 ssm.setAddTempFacAnnot(false);
509 ssm.setProcessSecondaryStructure(false);
510 ssm.setSecStructServices(false);
514 public void checkForNews()
516 final Desktop me = this;
517 // Thread off the news reader, in case there are connection problems.
518 new Thread(new Runnable()
523 Cache.log.debug("Starting news thread.");
525 jvnews = new BlogReader(me);
526 showNews.setVisible(true);
527 Cache.log.debug("Completed news thread.");
532 public void getIdentifiersOrgData()
534 // Thread off the identifiers fetcher
535 new Thread(new Runnable()
540 Cache.log.debug("Downloading data from identifiers.org");
541 UrlDownloadClient client = new UrlDownloadClient();
544 client.download(IdOrgSettings.getUrl(),
545 IdOrgSettings.getDownloadLocation());
546 } catch (IOException e)
548 Cache.log.debug("Exception downloading identifiers.org data"
557 protected void showNews_actionPerformed(ActionEvent e)
559 showNews(showNews.isSelected());
562 void showNews(boolean visible)
565 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
566 showNews.setSelected(visible);
567 if (visible && !jvnews.isVisible())
569 new Thread(new Runnable()
574 long now = System.currentTimeMillis();
575 Desktop.instance.setProgressBar(
576 MessageManager.getString("status.refreshing_news"),
578 jvnews.refreshNews();
579 Desktop.instance.setProgressBar(null, now);
588 * recover the last known dimensions for a jalview window
591 * - empty string is desktop, all other windows have unique prefix
592 * @return null or last known dimensions scaled to current geometry (if last
593 * window geom was known)
595 Rectangle getLastKnownDimensions(String windowName)
597 // TODO: lock aspect ratio for scaling desktop Bug #0058199
598 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
599 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
600 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
601 String width = jalview.bin.Cache
602 .getProperty(windowName + "SCREEN_WIDTH");
603 String height = jalview.bin.Cache
604 .getProperty(windowName + "SCREEN_HEIGHT");
605 if ((x != null) && (y != null) && (width != null) && (height != null))
607 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
608 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
609 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
611 // attempt #1 - try to cope with change in screen geometry - this
612 // version doesn't preserve original jv aspect ratio.
613 // take ratio of current screen size vs original screen size.
614 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
615 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
616 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
617 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
618 // rescale the bounds depending upon the current screen geometry.
619 ix = (int) (ix * sw);
620 iw = (int) (iw * sw);
621 iy = (int) (iy * sh);
622 ih = (int) (ih * sh);
623 while (ix >= screenSize.width)
625 jalview.bin.Cache.log.debug(
626 "Window geometry location recall error: shifting horizontal to within screenbounds.");
627 ix -= screenSize.width;
629 while (iy >= screenSize.height)
631 jalview.bin.Cache.log.debug(
632 "Window geometry location recall error: shifting vertical to within screenbounds.");
633 iy -= screenSize.height;
635 jalview.bin.Cache.log.debug(
636 "Got last known dimensions for " + windowName + ": x:" + ix
637 + " y:" + iy + " width:" + iw + " height:" + ih);
639 // return dimensions for new instance
640 return new Rectangle(ix, iy, iw, ih);
645 private void doVamsasClientCheck()
647 if (jalview.bin.Cache.vamsasJarsPresent())
649 setupVamsasDisconnectedGui();
650 VamsasMenu.setVisible(true);
651 final Desktop us = this;
652 VamsasMenu.addMenuListener(new MenuListener()
654 // this listener remembers when the menu was first selected, and
655 // doesn't rebuild the session list until it has been cleared and
657 boolean refresh = true;
660 public void menuCanceled(MenuEvent e)
666 public void menuDeselected(MenuEvent e)
672 public void menuSelected(MenuEvent e)
676 us.buildVamsasStMenu();
681 vamsasStart.setVisible(true);
685 void showPasteMenu(int x, int y)
687 JPopupMenu popup = new JPopupMenu();
688 JMenuItem item = new JMenuItem(
689 MessageManager.getString("label.paste_new_window"));
690 item.addActionListener(new ActionListener()
693 public void actionPerformed(ActionEvent evt)
700 popup.show(this, x, y);
707 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
708 Transferable contents = c.getContents(this);
710 if (contents != null)
712 String file = (String) contents
713 .getTransferData(DataFlavor.stringFlavor);
715 FileFormatI format = new IdentifyFile().identify(file,
716 DataSourceType.PASTE);
718 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
721 } catch (Exception ex)
724 "Unable to paste alignment from system clipboard:\n" + ex);
729 * Adds and opens the given frame to the desktop
740 public static synchronized void addInternalFrame(
741 final JInternalFrame frame, String title, int w, int h)
743 addInternalFrame(frame, title, true, w, h, true, false);
747 * Add an internal frame to the Jalview desktop
754 * When true, display frame immediately, otherwise, caller must call
755 * setVisible themselves.
761 public static synchronized void addInternalFrame(
762 final JInternalFrame frame, String title, boolean makeVisible,
765 addInternalFrame(frame, title, makeVisible, w, h, true, false);
769 * Add an internal frame to the Jalview desktop and make it visible
782 public static synchronized void addInternalFrame(
783 final JInternalFrame frame, String title, int w, int h,
786 addInternalFrame(frame, title, true, w, h, resizable, false);
790 * Add an internal frame to the Jalview desktop
797 * When true, display frame immediately, otherwise, caller must call
798 * setVisible themselves.
805 * @param ignoreMinSize
806 * Do not set the default minimum size for frame
808 public static synchronized void addInternalFrame(
809 final JInternalFrame frame, String title, boolean makeVisible,
810 int w, int h, boolean resizable, boolean ignoreMinSize)
813 // TODO: allow callers to determine X and Y position of frame (eg. via
815 // TODO: consider fixing method to update entries in the window submenu with
816 // the current window title
818 frame.setTitle(title);
819 if (frame.getWidth() < 1 || frame.getHeight() < 1)
823 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
824 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
825 // IF JALVIEW IS RUNNING HEADLESS
826 // ///////////////////////////////////////////////
827 if (instance == null || (System.getProperty("java.awt.headless") != null
828 && System.getProperty("java.awt.headless").equals("true")))
837 frame.setMinimumSize(
838 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
840 // Set default dimension for Alignment Frame window.
841 // The Alignment Frame window could be added from a number of places,
843 // I did this here in order not to miss out on any Alignment frame.
844 if (frame instanceof AlignFrame)
846 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
847 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
851 frame.setVisible(makeVisible);
852 frame.setClosable(true);
853 frame.setResizable(resizable);
854 frame.setMaximizable(resizable);
855 frame.setIconifiable(resizable);
856 frame.setOpaque(false);
858 if (frame.getX() < 1 && frame.getY() < 1)
860 frame.setLocation(xOffset * openFrameCount,
861 yOffset * ((openFrameCount - 1) % 10) + yOffset);
865 * add an entry for the new frame in the Window menu
866 * (and remove it when the frame is closed)
868 final JMenuItem menuItem = new JMenuItem(title);
869 frame.addInternalFrameListener(new InternalFrameAdapter()
872 public void internalFrameActivated(InternalFrameEvent evt)
874 JInternalFrame itf = desktop.getSelectedFrame();
877 if (itf instanceof AlignFrame)
879 Jalview.setCurrentAlignFrame((AlignFrame) itf);
886 public void internalFrameClosed(InternalFrameEvent evt)
888 PaintRefresher.RemoveComponent(frame);
891 * defensive check to prevent frames being
892 * added half off the window
894 if (openFrameCount > 0)
900 * ensure no reference to alignFrame retained by menu item listener
902 if (menuItem.getActionListeners().length > 0)
904 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
906 windowMenu.remove(menuItem);
912 menuItem.addActionListener(new ActionListener()
915 public void actionPerformed(ActionEvent e)
919 frame.setSelected(true);
920 frame.setIcon(false);
921 } catch (java.beans.PropertyVetoException ex)
930 windowMenu.add(menuItem);
935 frame.setSelected(true);
936 frame.requestFocus();
937 } catch (java.beans.PropertyVetoException ve)
939 } catch (java.lang.ClassCastException cex)
942 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
948 public void lostOwnership(Clipboard clipboard, Transferable contents)
952 Desktop.jalviewClipboard = null;
955 internalCopy = false;
959 public void dragEnter(DropTargetDragEvent evt)
964 public void dragExit(DropTargetEvent evt)
969 public void dragOver(DropTargetDragEvent evt)
974 public void dropActionChanged(DropTargetDragEvent evt)
985 public void drop(DropTargetDropEvent evt)
987 boolean success = true;
988 // JAL-1552 - acceptDrop required before getTransferable call for
989 // Java's Transferable for native dnd
990 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
991 Transferable t = evt.getTransferable();
992 List<String> files = new ArrayList<>();
993 List<DataSourceType> protocols = new ArrayList<>();
997 Desktop.transferFromDropTarget(files, protocols, evt, t);
998 } catch (Exception e)
1000 e.printStackTrace();
1008 for (int i = 0; i < files.size(); i++)
1010 String file = files.get(i).toString();
1011 DataSourceType protocol = (protocols == null)
1012 ? DataSourceType.FILE
1014 FileFormatI format = null;
1016 if (file.endsWith(".jar"))
1018 format = FileFormat.Jalview;
1023 format = new IdentifyFile().identify(file, protocol);
1026 new FileLoader().LoadFile(file, protocol, format);
1029 } catch (Exception ex)
1034 evt.dropComplete(success); // need this to ensure input focus is properly
1035 // transfered to any new windows created
1045 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1047 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1048 JalviewFileChooser chooser = JalviewFileChooser
1049 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1051 chooser.setFileView(new JalviewFileView());
1052 chooser.setDialogTitle(
1053 MessageManager.getString("label.open_local_file"));
1054 chooser.setToolTipText(MessageManager.getString("action.open"));
1056 int value = chooser.showOpenDialog(this);
1058 if (value == JalviewFileChooser.APPROVE_OPTION)
1060 String choice = chooser.getSelectedFile().getPath();
1061 Cache.setProperty("LAST_DIRECTORY",
1062 chooser.getSelectedFile().getParent());
1064 FileFormatI format = chooser.getSelectedFormat();
1067 * Call IdentifyFile to verify the file contains what its extension implies.
1068 * Skip this step for dynamically added file formats, because
1069 * IdentifyFile does not know how to recognise them.
1071 if (FileFormats.getInstance().isIdentifiable(format))
1075 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1076 } catch (FileFormatException e)
1078 // format = null; //??
1082 if (viewport != null)
1084 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1089 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1101 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1103 // This construct allows us to have a wider textfield
1105 JLabel label = new JLabel(
1106 MessageManager.getString("label.input_file_url"));
1107 final JComboBox history = new JComboBox();
1109 JPanel panel = new JPanel(new GridLayout(2, 1));
1112 history.setPreferredSize(new Dimension(400, 20));
1113 history.setEditable(true);
1114 history.addItem("http://www.");
1116 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1120 if (historyItems != null)
1122 st = new StringTokenizer(historyItems, "\t");
1124 while (st.hasMoreTokens())
1126 history.addItem(st.nextElement());
1130 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1131 MessageManager.getString("label.input_alignment_from_url"),
1132 JvOptionPane.OK_CANCEL_OPTION);
1134 if (reply != JvOptionPane.OK_OPTION)
1139 String url = history.getSelectedItem().toString();
1141 if (url.toLowerCase().endsWith(".jar"))
1143 if (viewport != null)
1145 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1146 FileFormat.Jalview);
1150 new FileLoader().LoadFile(url, DataSourceType.URL,
1151 FileFormat.Jalview);
1156 FileFormatI format = null;
1159 format = new IdentifyFile().identify(url, DataSourceType.URL);
1160 } catch (FileFormatException e)
1162 // TODO revise error handling, distinguish between
1163 // URL not found and response not valid
1168 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1169 MessageManager.formatMessage("label.couldnt_locate",
1172 MessageManager.getString("label.url_not_found"),
1173 JvOptionPane.WARNING_MESSAGE);
1178 if (viewport != null)
1180 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1185 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1191 * Opens the CutAndPaste window for the user to paste an alignment in to
1194 * - if not null, the pasted alignment is added to the current
1195 * alignment; if null, to a new alignment window
1198 public void inputTextboxMenuItem_actionPerformed(
1199 AlignmentViewPanel viewPanel)
1201 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1202 cap.setForInput(viewPanel);
1203 Desktop.addInternalFrame(cap,
1204 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1214 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1215 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1217 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1218 screen.height + "");
1219 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1220 getWidth(), getHeight()));
1222 if (jconsole != null)
1224 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1225 jconsole.stopConsole();
1229 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1232 if (dialogExecutor != null)
1234 dialogExecutor.shutdownNow();
1236 closeAll_actionPerformed(null);
1238 if (groovyConsole != null)
1240 // suppress a possible repeat prompt to save script
1241 groovyConsole.setDirty(false);
1242 groovyConsole.exit();
1247 private void storeLastKnownDimensions(String string, Rectangle jc)
1249 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1250 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1251 + " height:" + jc.height);
1253 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1254 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1255 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1256 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1266 public void aboutMenuItem_actionPerformed(ActionEvent e)
1268 // StringBuffer message = getAboutMessage(false);
1269 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1271 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1272 new Thread(new Runnable()
1277 new SplashScreen(true);
1282 public StringBuffer getAboutMessage(boolean shortv)
1284 StringBuffer message = new StringBuffer();
1285 message.append("<html>");
1288 message.append("<h1><strong>Version: "
1289 + jalview.bin.Cache.getProperty("VERSION")
1290 + "</strong></h1>");
1291 message.append("<strong>Last Updated: <em>"
1292 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1293 + "</em></strong>");
1299 message.append("<strong>Version "
1300 + jalview.bin.Cache.getProperty("VERSION")
1301 + "; last updated: "
1302 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1305 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1306 .equals("Checking"))
1308 message.append("<br>...Checking latest version...</br>");
1310 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1311 .equals(jalview.bin.Cache.getProperty("VERSION")))
1313 boolean red = false;
1314 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1315 .indexOf("automated build") == -1)
1318 // Displayed when code version and jnlp version do not match and code
1319 // version is not a development build
1320 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1323 message.append("<br>!! Version "
1324 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1326 + " is available for download from "
1327 + jalview.bin.Cache.getDefault("www.jalview.org",
1328 "http://www.jalview.org")
1332 message.append("</div>");
1335 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1337 "The Jalview Authors (See AUTHORS file for current list)")
1338 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1339 + "<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"
1340 + "<br><br>If you use Jalview, please cite:"
1341 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1342 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1343 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1355 public void documentationMenuItem_actionPerformed(ActionEvent e)
1359 Help.showHelpWindow();
1360 } catch (Exception ex)
1366 public void closeAll_actionPerformed(ActionEvent e)
1368 // TODO show a progress bar while closing?
1369 JInternalFrame[] frames = desktop.getAllFrames();
1370 for (int i = 0; i < frames.length; i++)
1374 frames[i].setClosed(true);
1375 } catch (java.beans.PropertyVetoException ex)
1379 Jalview.setCurrentAlignFrame(null);
1380 System.out.println("ALL CLOSED");
1381 if (v_client != null)
1383 // TODO clear binding to vamsas document objects on close_all
1387 * reset state of singleton objects as appropriate (clear down session state
1388 * when all windows are closed)
1390 StructureSelectionManager ssm = StructureSelectionManager
1391 .getStructureSelectionManager(this);
1400 public void raiseRelated_actionPerformed(ActionEvent e)
1402 reorderAssociatedWindows(false, false);
1406 public void minimizeAssociated_actionPerformed(ActionEvent e)
1408 reorderAssociatedWindows(true, false);
1411 void closeAssociatedWindows()
1413 reorderAssociatedWindows(false, true);
1419 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1423 protected void garbageCollect_actionPerformed(ActionEvent e)
1425 // We simply collect the garbage
1426 jalview.bin.Cache.log.debug("Collecting garbage...");
1428 jalview.bin.Cache.log.debug("Finished garbage collection.");
1435 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1439 protected void showMemusage_actionPerformed(ActionEvent e)
1441 desktop.showMemoryUsage(showMemusage.isSelected());
1448 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1452 protected void showConsole_actionPerformed(ActionEvent e)
1454 showConsole(showConsole.isSelected());
1457 Console jconsole = null;
1460 * control whether the java console is visible or not
1464 void showConsole(boolean selected)
1466 showConsole.setSelected(selected);
1467 // TODO: decide if we should update properties file
1468 Cache.setProperty("SHOW_JAVA_CONSOLE",
1469 Boolean.valueOf(selected).toString());
1470 jconsole.setVisible(selected);
1473 void reorderAssociatedWindows(boolean minimize, boolean close)
1475 JInternalFrame[] frames = desktop.getAllFrames();
1476 if (frames == null || frames.length < 1)
1481 AlignmentViewport source = null, target = null;
1482 if (frames[0] instanceof AlignFrame)
1484 source = ((AlignFrame) frames[0]).getCurrentView();
1486 else if (frames[0] instanceof TreePanel)
1488 source = ((TreePanel) frames[0]).getViewPort();
1490 else if (frames[0] instanceof PCAPanel)
1492 source = ((PCAPanel) frames[0]).av;
1494 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1496 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1501 for (int i = 0; i < frames.length; i++)
1504 if (frames[i] == null)
1508 if (frames[i] instanceof AlignFrame)
1510 target = ((AlignFrame) frames[i]).getCurrentView();
1512 else if (frames[i] instanceof TreePanel)
1514 target = ((TreePanel) frames[i]).getViewPort();
1516 else if (frames[i] instanceof PCAPanel)
1518 target = ((PCAPanel) frames[i]).av;
1520 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1522 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1525 if (source == target)
1531 frames[i].setClosed(true);
1535 frames[i].setIcon(minimize);
1538 frames[i].toFront();
1542 } catch (java.beans.PropertyVetoException ex)
1557 protected void preferences_actionPerformed(ActionEvent e)
1569 public void saveState_actionPerformed(ActionEvent e)
1571 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1574 chooser.setFileView(new JalviewFileView());
1575 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1577 int value = chooser.showSaveDialog(this);
1579 if (value == JalviewFileChooser.APPROVE_OPTION)
1581 final Desktop me = this;
1582 final java.io.File choice = chooser.getSelectedFile();
1583 setProjectFile(choice);
1585 new Thread(new Runnable()
1590 // TODO: refactor to Jalview desktop session controller action.
1591 setProgressBar(MessageManager.formatMessage(
1592 "label.saving_jalview_project", new Object[]
1593 { choice.getName() }), choice.hashCode());
1594 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1595 choice.getParent());
1596 // TODO catch and handle errors for savestate
1597 // TODO prevent user from messing with the Desktop whilst we're saving
1600 new Jalview2XML().saveState(choice);
1601 } catch (OutOfMemoryError oom)
1604 "Whilst saving current state to " + choice.getName(),
1606 } catch (Exception ex)
1609 "Problems whilst trying to save to " + choice.getName(),
1611 JvOptionPane.showMessageDialog(me,
1612 MessageManager.formatMessage(
1613 "label.error_whilst_saving_current_state_to",
1615 { choice.getName() }),
1616 MessageManager.getString("label.couldnt_save_project"),
1617 JvOptionPane.WARNING_MESSAGE);
1619 setProgressBar(null, choice.hashCode());
1625 private void setProjectFile(File choice)
1627 this.projectFile = choice;
1630 public File getProjectFile()
1632 return this.projectFile;
1642 public void loadState_actionPerformed(ActionEvent e)
1644 JalviewFileChooser chooser = new JalviewFileChooser(
1645 Cache.getProperty("LAST_DIRECTORY"), new String[]
1648 { "Jalview Project", "Jalview Project (old)" },
1650 chooser.setFileView(new JalviewFileView());
1651 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1653 int value = chooser.showOpenDialog(this);
1655 if (value == JalviewFileChooser.APPROVE_OPTION)
1657 final File selectedFile = chooser.getSelectedFile();
1658 setProjectFile(selectedFile);
1659 final String choice = selectedFile.getAbsolutePath();
1660 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1661 new Thread(new Runnable()
1666 setProgressBar(MessageManager.formatMessage(
1667 "label.loading_jalview_project", new Object[]
1668 { choice }), choice.hashCode());
1671 new Jalview2XML().loadJalviewAlign(choice);
1672 } catch (OutOfMemoryError oom)
1674 new OOMWarning("Whilst loading project from " + choice, oom);
1675 } catch (Exception ex)
1678 "Problems whilst loading project from " + choice, ex);
1679 JvOptionPane.showMessageDialog(Desktop.desktop,
1680 MessageManager.formatMessage(
1681 "label.error_whilst_loading_project_from",
1684 MessageManager.getString("label.couldnt_load_project"),
1685 JvOptionPane.WARNING_MESSAGE);
1687 setProgressBar(null, choice.hashCode());
1694 public void inputSequence_actionPerformed(ActionEvent e)
1696 new SequenceFetcher(this);
1699 JPanel progressPanel;
1701 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1703 public void startLoading(final String fileName)
1705 if (fileLoadingCount == 0)
1707 fileLoadingPanels.add(addProgressPanel(MessageManager
1708 .formatMessage("label.loading_file", new Object[]
1714 private JPanel addProgressPanel(String string)
1716 if (progressPanel == null)
1718 progressPanel = new JPanel(new GridLayout(1, 1));
1719 totalProgressCount = 0;
1720 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1722 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1723 JProgressBar progressBar = new JProgressBar();
1724 progressBar.setIndeterminate(true);
1726 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1728 thisprogress.add(progressBar, BorderLayout.CENTER);
1729 progressPanel.add(thisprogress);
1730 ((GridLayout) progressPanel.getLayout()).setRows(
1731 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1732 ++totalProgressCount;
1733 instance.validate();
1734 return thisprogress;
1737 int totalProgressCount = 0;
1739 private void removeProgressPanel(JPanel progbar)
1741 if (progressPanel != null)
1743 synchronized (progressPanel)
1745 progressPanel.remove(progbar);
1746 GridLayout gl = (GridLayout) progressPanel.getLayout();
1747 gl.setRows(gl.getRows() - 1);
1748 if (--totalProgressCount < 1)
1750 this.getContentPane().remove(progressPanel);
1751 progressPanel = null;
1758 public void stopLoading()
1761 if (fileLoadingCount < 1)
1763 while (fileLoadingPanels.size() > 0)
1765 removeProgressPanel(fileLoadingPanels.remove(0));
1767 fileLoadingPanels.clear();
1768 fileLoadingCount = 0;
1773 public static int getViewCount(String alignmentId)
1775 AlignmentViewport[] aps = getViewports(alignmentId);
1776 return (aps == null) ? 0 : aps.length;
1781 * @param alignmentId
1782 * - if null, all sets are returned
1783 * @return all AlignmentPanels concerning the alignmentId sequence set
1785 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1787 if (Desktop.desktop == null)
1789 // no frames created and in headless mode
1790 // TODO: verify that frames are recoverable when in headless mode
1793 List<AlignmentPanel> aps = new ArrayList<>();
1794 AlignFrame[] frames = getAlignFrames();
1799 for (AlignFrame af : frames)
1801 for (AlignmentPanel ap : af.alignPanels)
1803 if (alignmentId == null
1804 || alignmentId.equals(ap.av.getSequenceSetId()))
1810 if (aps.size() == 0)
1814 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1819 * get all the viewports on an alignment.
1821 * @param sequenceSetId
1822 * unique alignment id (may be null - all viewports returned in that
1824 * @return all viewports on the alignment bound to sequenceSetId
1826 public static AlignmentViewport[] getViewports(String sequenceSetId)
1828 List<AlignmentViewport> viewp = new ArrayList<>();
1829 if (desktop != null)
1831 AlignFrame[] frames = Desktop.getAlignFrames();
1833 for (AlignFrame afr : frames)
1835 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1836 .equals(sequenceSetId))
1838 if (afr.alignPanels != null)
1840 for (AlignmentPanel ap : afr.alignPanels)
1842 if (sequenceSetId == null
1843 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1851 viewp.add(afr.getViewport());
1855 if (viewp.size() > 0)
1857 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1864 * Explode the views in the given frame into separate AlignFrame
1868 public static void explodeViews(AlignFrame af)
1870 int size = af.alignPanels.size();
1876 for (int i = 0; i < size; i++)
1878 AlignmentPanel ap = af.alignPanels.get(i);
1879 AlignFrame newaf = new AlignFrame(ap);
1882 * Restore the view's last exploded frame geometry if known. Multiple
1883 * views from one exploded frame share and restore the same (frame)
1884 * position and size.
1886 Rectangle geometry = ap.av.getExplodedGeometry();
1887 if (geometry != null)
1889 newaf.setBounds(geometry);
1892 ap.av.setGatherViewsHere(false);
1894 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1895 AlignFrame.DEFAULT_HEIGHT);
1898 af.alignPanels.clear();
1899 af.closeMenuItem_actionPerformed(true);
1904 * Gather expanded views (separate AlignFrame's) with the same sequence set
1905 * identifier back in to this frame as additional views, and close the
1906 * expanded views. Note the expanded frames may themselves have multiple
1907 * views. We take the lot.
1911 public void gatherViews(AlignFrame source)
1913 source.viewport.setGatherViewsHere(true);
1914 source.viewport.setExplodedGeometry(source.getBounds());
1915 JInternalFrame[] frames = desktop.getAllFrames();
1916 String viewId = source.viewport.getSequenceSetId();
1918 for (int t = 0; t < frames.length; t++)
1920 if (frames[t] instanceof AlignFrame && frames[t] != source)
1922 AlignFrame af = (AlignFrame) frames[t];
1923 boolean gatherThis = false;
1924 for (int a = 0; a < af.alignPanels.size(); a++)
1926 AlignmentPanel ap = af.alignPanels.get(a);
1927 if (viewId.equals(ap.av.getSequenceSetId()))
1930 ap.av.setGatherViewsHere(false);
1931 ap.av.setExplodedGeometry(af.getBounds());
1932 source.addAlignmentPanel(ap, false);
1938 af.alignPanels.clear();
1939 af.closeMenuItem_actionPerformed(true);
1943 for (AlignmentPanel ap : source.alignPanels)
1945 SwingUtilities.invokeLater(new Runnable() {
1949 ap.setSize(ap.getSize());
1956 jalview.gui.VamsasApplication v_client = null;
1959 public void vamsasImport_actionPerformed(ActionEvent e)
1961 if (v_client == null)
1963 // Load and try to start a session.
1964 JalviewFileChooser chooser = new JalviewFileChooser(
1965 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1967 chooser.setFileView(new JalviewFileView());
1968 chooser.setDialogTitle(
1969 MessageManager.getString("label.open_saved_vamsas_session"));
1970 chooser.setToolTipText(MessageManager.getString(
1971 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1973 int value = chooser.showOpenDialog(this);
1975 if (value == JalviewFileChooser.APPROVE_OPTION)
1977 String fle = chooser.getSelectedFile().toString();
1978 if (!vamsasImport(chooser.getSelectedFile()))
1980 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1981 MessageManager.formatMessage(
1982 "label.couldnt_import_as_vamsas_session",
1986 .getString("label.vamsas_document_import_failed"),
1987 JvOptionPane.ERROR_MESSAGE);
1993 jalview.bin.Cache.log.error(
1994 "Implementation error - load session from a running session is not supported.");
1999 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2002 * @return true if import was a success and a session was started.
2004 public boolean vamsasImport(URL url)
2006 // TODO: create progress bar
2007 if (v_client != null)
2010 jalview.bin.Cache.log.error(
2011 "Implementation error - load session from a running session is not supported.");
2017 // copy the URL content to a temporary local file
2018 // TODO: be a bit cleverer here with nio (?!)
2019 File file = File.createTempFile("vdocfromurl", ".vdj");
2020 FileOutputStream fos = new FileOutputStream(file);
2021 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2022 byte[] buffer = new byte[2048];
2024 while ((ln = bis.read(buffer)) > -1)
2026 fos.write(buffer, 0, ln);
2030 v_client = new jalview.gui.VamsasApplication(this, file,
2031 url.toExternalForm());
2032 } catch (Exception ex)
2034 jalview.bin.Cache.log.error(
2035 "Failed to create new vamsas session from contents of URL "
2040 setupVamsasConnectedGui();
2041 v_client.initial_update(); // TODO: thread ?
2042 return v_client.inSession();
2046 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2049 * @return true if import was a success and a session was started.
2051 public boolean vamsasImport(File file)
2053 if (v_client != null)
2056 jalview.bin.Cache.log.error(
2057 "Implementation error - load session from a running session is not supported.");
2061 setProgressBar(MessageManager.formatMessage(
2062 "status.importing_vamsas_session_from", new Object[]
2063 { file.getName() }), file.hashCode());
2066 v_client = new jalview.gui.VamsasApplication(this, file, null);
2067 } catch (Exception ex)
2069 setProgressBar(MessageManager.formatMessage(
2070 "status.importing_vamsas_session_from", new Object[]
2071 { file.getName() }), file.hashCode());
2072 jalview.bin.Cache.log.error(
2073 "New vamsas session from existing session file failed:", ex);
2076 setupVamsasConnectedGui();
2077 v_client.initial_update(); // TODO: thread ?
2078 setProgressBar(MessageManager.formatMessage(
2079 "status.importing_vamsas_session_from", new Object[]
2080 { file.getName() }), file.hashCode());
2081 return v_client.inSession();
2084 public boolean joinVamsasSession(String mysesid)
2086 if (v_client != null)
2088 throw new Error(MessageManager
2089 .getString("error.try_join_vamsas_session_another"));
2091 if (mysesid == null)
2094 MessageManager.getString("error.invalid_vamsas_session_id"));
2096 v_client = new VamsasApplication(this, mysesid);
2097 setupVamsasConnectedGui();
2098 v_client.initial_update();
2099 return (v_client.inSession());
2103 public void vamsasStart_actionPerformed(ActionEvent e)
2105 if (v_client == null)
2108 // we just start a default session for moment.
2110 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2111 * getProperty("LAST_DIRECTORY"));
2113 * chooser.setFileView(new JalviewFileView());
2114 * chooser.setDialogTitle("Load Vamsas file");
2115 * chooser.setToolTipText("Import");
2117 * int value = chooser.showOpenDialog(this);
2119 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2120 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2122 v_client = new VamsasApplication(this);
2123 setupVamsasConnectedGui();
2124 v_client.initial_update(); // TODO: thread ?
2128 // store current data in session.
2129 v_client.push_update(); // TODO: thread
2133 protected void setupVamsasConnectedGui()
2135 vamsasStart.setText(MessageManager.getString("label.session_update"));
2136 vamsasSave.setVisible(true);
2137 vamsasStop.setVisible(true);
2138 vamsasImport.setVisible(false); // Document import to existing session is
2139 // not possible for vamsas-client-1.0.
2142 protected void setupVamsasDisconnectedGui()
2144 vamsasSave.setVisible(false);
2145 vamsasStop.setVisible(false);
2146 vamsasImport.setVisible(true);
2148 .setText(MessageManager.getString("label.new_vamsas_session"));
2152 public void vamsasStop_actionPerformed(ActionEvent e)
2154 if (v_client != null)
2156 v_client.end_session();
2158 setupVamsasDisconnectedGui();
2162 protected void buildVamsasStMenu()
2164 if (v_client == null)
2166 String[] sess = null;
2169 sess = VamsasApplication.getSessionList();
2170 } catch (Exception e)
2172 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2178 jalview.bin.Cache.log.debug(
2179 "Got current sessions list: " + sess.length + " entries.");
2180 VamsasStMenu.removeAll();
2181 for (int i = 0; i < sess.length; i++)
2183 JMenuItem sessit = new JMenuItem();
2184 sessit.setText(sess[i]);
2185 sessit.setToolTipText(MessageManager
2186 .formatMessage("label.connect_to_session", new Object[]
2188 final Desktop dsktp = this;
2189 final String mysesid = sess[i];
2190 sessit.addActionListener(new ActionListener()
2194 public void actionPerformed(ActionEvent e)
2196 if (dsktp.v_client == null)
2198 Thread rthr = new Thread(new Runnable()
2204 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2205 dsktp.setupVamsasConnectedGui();
2206 dsktp.v_client.initial_update();
2214 VamsasStMenu.add(sessit);
2216 // don't show an empty menu.
2217 VamsasStMenu.setVisible(sess.length > 0);
2222 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2223 VamsasStMenu.removeAll();
2224 VamsasStMenu.setVisible(false);
2229 // Not interested in the content. Just hide ourselves.
2230 VamsasStMenu.setVisible(false);
2235 public void vamsasSave_actionPerformed(ActionEvent e)
2237 if (v_client != null)
2239 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2240 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2243 chooser.setFileView(new JalviewFileView());
2244 chooser.setDialogTitle(MessageManager
2245 .getString("label.save_vamsas_document_archive"));
2247 int value = chooser.showSaveDialog(this);
2249 if (value == JalviewFileChooser.APPROVE_OPTION)
2251 java.io.File choice = chooser.getSelectedFile();
2252 JPanel progpanel = addProgressPanel(MessageManager
2253 .formatMessage("label.saving_vamsas_doc", new Object[]
2254 { choice.getName() }));
2255 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2256 String warnmsg = null;
2257 String warnttl = null;
2260 v_client.vclient.storeDocument(choice);
2263 warnttl = "Serious Problem saving Vamsas Document";
2264 warnmsg = ex.toString();
2265 jalview.bin.Cache.log
2266 .error("Error Whilst saving document to " + choice, ex);
2268 } catch (Exception ex)
2270 warnttl = "Problem saving Vamsas Document.";
2271 warnmsg = ex.toString();
2272 jalview.bin.Cache.log.warn(
2273 "Exception Whilst saving document to " + choice, ex);
2276 removeProgressPanel(progpanel);
2277 if (warnmsg != null)
2279 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2281 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2287 JPanel vamUpdate = null;
2290 * hide vamsas user gui bits when a vamsas document event is being handled.
2293 * true to hide gui, false to reveal gui
2295 public void setVamsasUpdate(boolean b)
2297 Cache.log.debug("Setting gui for Vamsas update "
2298 + (b ? "in progress" : "finished"));
2300 if (vamUpdate != null)
2302 this.removeProgressPanel(vamUpdate);
2306 vamUpdate = this.addProgressPanel(
2307 MessageManager.getString("label.updating_vamsas_session"));
2309 vamsasStart.setVisible(!b);
2310 vamsasStop.setVisible(!b);
2311 vamsasSave.setVisible(!b);
2314 public JInternalFrame[] getAllFrames()
2316 return desktop.getAllFrames();
2320 * Checks the given url to see if it gives a response indicating that the user
2321 * should be informed of a new questionnaire.
2325 public void checkForQuestionnaire(String url)
2327 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2328 // javax.swing.SwingUtilities.invokeLater(jvq);
2329 new Thread(jvq).start();
2332 public void checkURLLinks()
2334 // Thread off the URL link checker
2335 addDialogThread(new Runnable()
2340 if (Cache.getDefault("CHECKURLLINKS", true))
2342 // check what the actual links are - if it's just the default don't
2343 // bother with the warning
2344 List<String> links = Preferences.sequenceUrlLinks
2347 // only need to check links if there is one with a
2348 // SEQUENCE_ID which is not the default EMBL_EBI link
2349 ListIterator<String> li = links.listIterator();
2350 boolean check = false;
2351 List<JLabel> urls = new ArrayList<>();
2352 while (li.hasNext())
2354 String link = li.next();
2355 if (link.contains(SEQUENCE_ID)
2356 && !UrlConstants.isDefaultString(link))
2359 int barPos = link.indexOf("|");
2360 String urlMsg = barPos == -1 ? link
2361 : link.substring(0, barPos) + ": "
2362 + link.substring(barPos + 1);
2363 urls.add(new JLabel(urlMsg));
2371 // ask user to check in case URL links use old style tokens
2372 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2373 JPanel msgPanel = new JPanel();
2374 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2375 msgPanel.add(Box.createVerticalGlue());
2376 JLabel msg = new JLabel(MessageManager
2377 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2378 JLabel msg2 = new JLabel(MessageManager
2379 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2381 for (JLabel url : urls)
2387 final JCheckBox jcb = new JCheckBox(
2388 MessageManager.getString("label.do_not_display_again"));
2389 jcb.addActionListener(new ActionListener()
2392 public void actionPerformed(ActionEvent e)
2394 // update Cache settings for "don't show this again"
2395 boolean showWarningAgain = !jcb.isSelected();
2396 Cache.setProperty("CHECKURLLINKS",
2397 Boolean.valueOf(showWarningAgain).toString());
2402 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2404 .getString("label.SEQUENCE_ID_no_longer_used"),
2405 JvOptionPane.WARNING_MESSAGE);
2412 * Proxy class for JDesktopPane which optionally displays the current memory
2413 * usage and highlights the desktop area with a red bar if free memory runs
2418 public class MyDesktopPane extends JDesktopPane implements Runnable
2421 private static final float ONE_MB = 1048576f;
2423 boolean showMemoryUsage = false;
2427 java.text.NumberFormat df;
2429 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2432 public MyDesktopPane(boolean showMemoryUsage)
2434 showMemoryUsage(showMemoryUsage);
2437 public void showMemoryUsage(boolean showMemory)
2439 this.showMemoryUsage = showMemory;
2442 Thread worker = new Thread(this);
2448 public boolean isShowMemoryUsage()
2450 return showMemoryUsage;
2456 df = java.text.NumberFormat.getNumberInstance();
2457 df.setMaximumFractionDigits(2);
2458 runtime = Runtime.getRuntime();
2460 while (showMemoryUsage)
2464 maxMemory = runtime.maxMemory() / ONE_MB;
2465 allocatedMemory = runtime.totalMemory() / ONE_MB;
2466 freeMemory = runtime.freeMemory() / ONE_MB;
2467 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2469 percentUsage = (totalFreeMemory / maxMemory) * 100;
2471 // if (percentUsage < 20)
2473 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2475 // instance.set.setBorder(border1);
2478 // sleep after showing usage
2480 } catch (Exception ex)
2482 ex.printStackTrace();
2488 public void paintComponent(Graphics g)
2490 if (showMemoryUsage && g != null && df != null)
2492 if (percentUsage < 20)
2494 g.setColor(Color.red);
2496 FontMetrics fm = g.getFontMetrics();
2499 g.drawString(MessageManager.formatMessage("label.memory_stats",
2501 { df.format(totalFreeMemory), df.format(maxMemory),
2502 df.format(percentUsage) }),
2503 10, getHeight() - fm.getHeight());
2511 * Accessor method to quickly get all the AlignmentFrames loaded.
2513 * @return an array of AlignFrame, or null if none found
2515 public static AlignFrame[] getAlignFrames()
2517 if (Jalview.isHeadlessMode())
2519 // Desktop.desktop is null in headless mode
2520 return new AlignFrame[] { Jalview.currentAlignFrame };
2523 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2529 List<AlignFrame> avp = new ArrayList<>();
2531 for (int i = frames.length - 1; i > -1; i--)
2533 if (frames[i] instanceof AlignFrame)
2535 avp.add((AlignFrame) frames[i]);
2537 else if (frames[i] instanceof SplitFrame)
2540 * Also check for a split frame containing an AlignFrame
2542 GSplitFrame sf = (GSplitFrame) frames[i];
2543 if (sf.getTopFrame() instanceof AlignFrame)
2545 avp.add((AlignFrame) sf.getTopFrame());
2547 if (sf.getBottomFrame() instanceof AlignFrame)
2549 avp.add((AlignFrame) sf.getBottomFrame());
2553 if (avp.size() == 0)
2557 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2562 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2566 public GStructureViewer[] getJmols()
2568 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2574 List<GStructureViewer> avp = new ArrayList<>();
2576 for (int i = frames.length - 1; i > -1; i--)
2578 if (frames[i] instanceof AppJmol)
2580 GStructureViewer af = (GStructureViewer) frames[i];
2584 if (avp.size() == 0)
2588 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2593 * Add Groovy Support to Jalview
2596 public void groovyShell_actionPerformed()
2600 openGroovyConsole();
2601 } catch (Exception ex)
2603 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2604 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2606 MessageManager.getString("label.couldnt_create_groovy_shell"),
2607 MessageManager.getString("label.groovy_support_failed"),
2608 JvOptionPane.ERROR_MESSAGE);
2613 * Open the Groovy console
2615 void openGroovyConsole()
2617 if (groovyConsole == null)
2619 groovyConsole = new groovy.ui.Console();
2620 groovyConsole.setVariable("Jalview", this);
2621 groovyConsole.run();
2624 * We allow only one console at a time, so that AlignFrame menu option
2625 * 'Calculate | Run Groovy script' is unambiguous.
2626 * Disable 'Groovy Console', and enable 'Run script', when the console is
2627 * opened, and the reverse when it is closed
2629 Window window = (Window) groovyConsole.getFrame();
2630 window.addWindowListener(new WindowAdapter()
2633 public void windowClosed(WindowEvent e)
2636 * rebind CMD-Q from Groovy Console to Jalview Quit
2639 enableExecuteGroovy(false);
2645 * show Groovy console window (after close and reopen)
2647 ((Window) groovyConsole.getFrame()).setVisible(true);
2650 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2651 * and disable opening a second console
2653 enableExecuteGroovy(true);
2657 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2658 * binding when opened
2660 protected void addQuitHandler()
2662 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2663 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2664 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2666 getRootPane().getActionMap().put("Quit", new AbstractAction()
2669 public void actionPerformed(ActionEvent e)
2677 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2680 * true if Groovy console is open
2682 public void enableExecuteGroovy(boolean enabled)
2685 * disable opening a second Groovy console
2686 * (or re-enable when the console is closed)
2688 groovyShell.setEnabled(!enabled);
2690 AlignFrame[] alignFrames = getAlignFrames();
2691 if (alignFrames != null)
2693 for (AlignFrame af : alignFrames)
2695 af.setGroovyEnabled(enabled);
2701 * Progress bars managed by the IProgressIndicator method.
2703 private Hashtable<Long, JPanel> progressBars;
2705 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2710 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2713 public void setProgressBar(String message, long id)
2715 if (progressBars == null)
2717 progressBars = new Hashtable<>();
2718 progressBarHandlers = new Hashtable<>();
2721 if (progressBars.get(new Long(id)) != null)
2723 JPanel panel = progressBars.remove(new Long(id));
2724 if (progressBarHandlers.contains(new Long(id)))
2726 progressBarHandlers.remove(new Long(id));
2728 removeProgressPanel(panel);
2732 progressBars.put(new Long(id), addProgressPanel(message));
2739 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2740 * jalview.gui.IProgressIndicatorHandler)
2743 public void registerHandler(final long id,
2744 final IProgressIndicatorHandler handler)
2746 if (progressBarHandlers == null
2747 || !progressBars.containsKey(new Long(id)))
2749 throw new Error(MessageManager.getString(
2750 "error.call_setprogressbar_before_registering_handler"));
2752 progressBarHandlers.put(new Long(id), handler);
2753 final JPanel progressPanel = progressBars.get(new Long(id));
2754 if (handler.canCancel())
2756 JButton cancel = new JButton(
2757 MessageManager.getString("action.cancel"));
2758 final IProgressIndicator us = this;
2759 cancel.addActionListener(new ActionListener()
2763 public void actionPerformed(ActionEvent e)
2765 handler.cancelActivity(id);
2766 us.setProgressBar(MessageManager
2767 .formatMessage("label.cancelled_params", new Object[]
2768 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2772 progressPanel.add(cancel, BorderLayout.EAST);
2778 * @return true if any progress bars are still active
2781 public boolean operationInProgress()
2783 if (progressBars != null && progressBars.size() > 0)
2791 * This will return the first AlignFrame holding the given viewport instance.
2792 * It will break if there are more than one AlignFrames viewing a particular
2796 * @return alignFrame for viewport
2798 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2800 if (desktop != null)
2802 AlignmentPanel[] aps = getAlignmentPanels(
2803 viewport.getSequenceSetId());
2804 for (int panel = 0; aps != null && panel < aps.length; panel++)
2806 if (aps[panel] != null && aps[panel].av == viewport)
2808 return aps[panel].alignFrame;
2815 public VamsasApplication getVamsasApplication()
2822 * flag set if jalview GUI is being operated programmatically
2824 private boolean inBatchMode = false;
2827 * check if jalview GUI is being operated programmatically
2829 * @return inBatchMode
2831 public boolean isInBatchMode()
2837 * set flag if jalview GUI is being operated programmatically
2839 * @param inBatchMode
2841 public void setInBatchMode(boolean inBatchMode)
2843 this.inBatchMode = inBatchMode;
2846 public void startServiceDiscovery()
2848 startServiceDiscovery(false);
2851 public void startServiceDiscovery(boolean blocking)
2853 boolean alive = true;
2854 Thread t0 = null, t1 = null, t2 = null;
2855 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2858 // todo: changesupport handlers need to be transferred
2859 if (discoverer == null)
2861 discoverer = new jalview.ws.jws1.Discoverer();
2862 // register PCS handler for desktop.
2863 discoverer.addPropertyChangeListener(changeSupport);
2865 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2866 // until we phase out completely
2867 (t0 = new Thread(discoverer)).start();
2870 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2872 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2873 .startDiscoverer(changeSupport);
2877 // TODO: do rest service discovery
2886 } catch (Exception e)
2889 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2890 || (t3 != null && t3.isAlive())
2891 || (t0 != null && t0.isAlive());
2897 * called to check if the service discovery process completed successfully.
2901 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2903 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2905 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2906 .getErrorMessages();
2909 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2911 if (serviceChangedDialog == null)
2913 // only run if we aren't already displaying one of these.
2914 addDialogThread(serviceChangedDialog = new Runnable()
2921 * JalviewDialog jd =new JalviewDialog() {
2923 * @Override protected void cancelPressed() { // TODO
2924 * Auto-generated method stub
2926 * }@Override protected void okPressed() { // TODO
2927 * Auto-generated method stub
2929 * }@Override protected void raiseClosed() { // TODO
2930 * Auto-generated method stub
2932 * } }; jd.initDialogFrame(new
2933 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2934 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2935 * + " or mis-configured HTTP proxy settings.<br/>" +
2936 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2938 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2939 * ), true, true, "Web Service Configuration Problem", 450,
2942 * jd.waitForInput();
2944 JvOptionPane.showConfirmDialog(Desktop.desktop,
2945 new JLabel("<html><table width=\"450\"><tr><td>"
2946 + ermsg + "</td></tr></table>"
2947 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2948 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2949 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2950 + " Tools->Preferences dialog box to change them.</p></html>"),
2951 "Web Service Configuration Problem",
2952 JvOptionPane.DEFAULT_OPTION,
2953 JvOptionPane.ERROR_MESSAGE);
2954 serviceChangedDialog = null;
2963 "Errors reported by JABA discovery service. Check web services preferences.\n"
2970 private Runnable serviceChangedDialog = null;
2973 * start a thread to open a URL in the configured browser. Pops up a warning
2974 * dialog to the user if there is an exception when calling out to the browser
2979 public static void showUrl(final String url)
2981 showUrl(url, Desktop.instance);
2985 * Like showUrl but allows progress handler to be specified
2989 * (null) or object implementing IProgressIndicator
2991 public static void showUrl(final String url,
2992 final IProgressIndicator progress)
2994 new Thread(new Runnable()
3001 if (progress != null)
3003 progress.setProgressBar(MessageManager
3004 .formatMessage("status.opening_params", new Object[]
3005 { url }), this.hashCode());
3007 jalview.util.BrowserLauncher.openURL(url);
3008 } catch (Exception ex)
3010 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3012 .getString("label.web_browser_not_found_unix"),
3013 MessageManager.getString("label.web_browser_not_found"),
3014 JvOptionPane.WARNING_MESSAGE);
3016 ex.printStackTrace();
3018 if (progress != null)
3020 progress.setProgressBar(null, this.hashCode());
3026 public static WsParamSetManager wsparamManager = null;
3028 public static ParamManager getUserParameterStore()
3030 if (wsparamManager == null)
3032 wsparamManager = new WsParamSetManager();
3034 return wsparamManager;
3038 * static hyperlink handler proxy method for use by Jalview's internal windows
3042 public static void hyperlinkUpdate(HyperlinkEvent e)
3044 if (e.getEventType() == EventType.ACTIVATED)
3049 url = e.getURL().toString();
3050 Desktop.showUrl(url);
3051 } catch (Exception x)
3055 if (Cache.log != null)
3057 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3062 "Couldn't handle string " + url + " as a URL.");
3065 // ignore any exceptions due to dud links.
3072 * single thread that handles display of dialogs to user.
3074 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3077 * flag indicating if dialogExecutor should try to acquire a permit
3079 private volatile boolean dialogPause = true;
3084 private java.util.concurrent.Semaphore block = new Semaphore(0);
3086 private static groovy.ui.Console groovyConsole;
3089 * add another dialog thread to the queue
3093 public void addDialogThread(final Runnable prompter)
3095 dialogExecutor.submit(new Runnable()
3105 } catch (InterruptedException x)
3110 if (instance == null)
3116 SwingUtilities.invokeAndWait(prompter);
3117 } catch (Exception q)
3119 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3125 public void startDialogQueue()
3127 // set the flag so we don't pause waiting for another permit and semaphore
3128 // the current task to begin
3129 dialogPause = false;
3134 protected void snapShotWindow_actionPerformed(ActionEvent e)
3138 ImageMaker im = new jalview.util.ImageMaker(
3139 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3140 getHeight(), of = new File("Jalview_snapshot"
3141 + System.currentTimeMillis() + ".eps"),
3142 "View of desktop", null, 0, false);
3145 paintAll(im.getGraphics());
3147 } catch (Exception q)
3149 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3153 Cache.log.info("Successfully written snapshot to file "
3154 + of.getAbsolutePath());
3158 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3159 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3160 * and location last time the view was expanded (if any). However it does not
3161 * remember the split pane divider location - this is set to match the
3162 * 'exploding' frame.
3166 public void explodeViews(SplitFrame sf)
3168 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3169 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3170 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3172 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3174 int viewCount = topPanels.size();
3181 * Processing in reverse order works, forwards order leaves the first panels
3182 * not visible. I don't know why!
3184 for (int i = viewCount - 1; i >= 0; i--)
3187 * Make new top and bottom frames. These take over the respective
3188 * AlignmentPanel objects, including their AlignmentViewports, so the
3189 * cdna/protein relationships between the viewports is carried over to the
3192 * explodedGeometry holds the (x, y) position of the previously exploded
3193 * SplitFrame, and the (width, height) of the AlignFrame component
3195 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3196 AlignFrame newTopFrame = new AlignFrame(topPanel);
3197 newTopFrame.setSize(oldTopFrame.getSize());
3198 newTopFrame.setVisible(true);
3199 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3200 .getExplodedGeometry();
3201 if (geometry != null)
3203 newTopFrame.setSize(geometry.getSize());
3206 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3207 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3208 newBottomFrame.setSize(oldBottomFrame.getSize());
3209 newBottomFrame.setVisible(true);
3210 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3211 .getExplodedGeometry();
3212 if (geometry != null)
3214 newBottomFrame.setSize(geometry.getSize());
3217 topPanel.av.setGatherViewsHere(false);
3218 bottomPanel.av.setGatherViewsHere(false);
3219 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3221 if (geometry != null)
3223 splitFrame.setLocation(geometry.getLocation());
3225 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3229 * Clear references to the panels (now relocated in the new SplitFrames)
3230 * before closing the old SplitFrame.
3233 bottomPanels.clear();
3238 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3239 * back into the given SplitFrame as additional views. Note that the gathered
3240 * frames may themselves have multiple views.
3244 public void gatherViews(GSplitFrame source)
3247 * special handling of explodedGeometry for a view within a SplitFrame: - it
3248 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3249 * height) of the AlignFrame component
3251 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3252 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3253 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3254 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3255 myBottomFrame.viewport
3256 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3257 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3258 myTopFrame.viewport.setGatherViewsHere(true);
3259 myBottomFrame.viewport.setGatherViewsHere(true);
3260 String topViewId = myTopFrame.viewport.getSequenceSetId();
3261 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3263 JInternalFrame[] frames = desktop.getAllFrames();
3264 for (JInternalFrame frame : frames)
3266 if (frame instanceof SplitFrame && frame != source)
3268 SplitFrame sf = (SplitFrame) frame;
3269 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3270 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3271 boolean gatherThis = false;
3272 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3274 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3275 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3276 if (topViewId.equals(topPanel.av.getSequenceSetId())
3277 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3280 topPanel.av.setGatherViewsHere(false);
3281 bottomPanel.av.setGatherViewsHere(false);
3282 topPanel.av.setExplodedGeometry(
3283 new Rectangle(sf.getLocation(), topFrame.getSize()));
3284 bottomPanel.av.setExplodedGeometry(
3285 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3286 myTopFrame.addAlignmentPanel(topPanel, false);
3287 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3293 topFrame.getAlignPanels().clear();
3294 bottomFrame.getAlignPanels().clear();
3301 * The dust settles...give focus to the tab we did this from.
3303 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3306 public static groovy.ui.Console getGroovyConsole()
3308 return groovyConsole;
3312 * handles the payload of a drag and drop event.
3314 * TODO refactor to desktop utilities class
3317 * - Data source strings extracted from the drop event
3319 * - protocol for each data source extracted from the drop event
3323 * - the payload from the drop event
3326 public static void transferFromDropTarget(List<String> files,
3327 List<DataSourceType> protocols, DropTargetDropEvent evt,
3328 Transferable t) throws Exception
3331 DataFlavor uriListFlavor = new DataFlavor(
3332 "text/uri-list;class=java.lang.String"), urlFlavour = null;
3335 urlFlavour = new DataFlavor(
3336 "application/x-java-url; class=java.net.URL");
3337 } catch (ClassNotFoundException cfe)
3339 Cache.log.debug("Couldn't instantiate the URL dataflavor.", cfe);
3342 if (urlFlavour != null && t.isDataFlavorSupported(urlFlavour))
3347 java.net.URL url = (URL) t.getTransferData(urlFlavour);
3348 // nb: java 8 osx bug https://bugs.openjdk.java.net/browse/JDK-8156099
3349 // means url may be null.
3352 protocols.add(DataSourceType.URL);
3353 files.add(url.toString());
3354 Cache.log.debug("Drop handled as URL dataflavor "
3355 + files.get(files.size() - 1));
3360 if (Platform.isAMac())
3363 "Please ignore plist error - occurs due to problem with java 8 on OSX");
3367 } catch (Throwable ex)
3369 Cache.log.debug("URL drop handler failed.", ex);
3372 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3374 // Works on Windows and MacOSX
3375 Cache.log.debug("Drop handled as javaFileListFlavor");
3376 for (Object file : (List) t
3377 .getTransferData(DataFlavor.javaFileListFlavor))
3379 files.add(((File) file).toString());
3380 protocols.add(DataSourceType.FILE);
3385 // Unix like behaviour
3386 boolean added = false;
3388 if (t.isDataFlavorSupported(uriListFlavor))
3390 Cache.log.debug("Drop handled as uriListFlavor");
3391 // This is used by Unix drag system
3392 data = (String) t.getTransferData(uriListFlavor);
3396 // fallback to text: workaround - on OSX where there's a JVM bug
3397 Cache.log.debug("standard URIListFlavor failed. Trying text");
3398 // try text fallback
3399 DataFlavor textDf = new DataFlavor(
3400 "text/plain;class=java.lang.String");
3401 if (t.isDataFlavorSupported(textDf))
3403 data = (String) t.getTransferData(textDf);
3406 Cache.log.debug("Plain text drop content returned "
3407 + (data == null ? "Null - failed" : data));
3412 while (protocols.size() < files.size())
3414 Cache.log.debug("Adding missing FILE protocol for "
3415 + files.get(protocols.size()));
3416 protocols.add(DataSourceType.FILE);
3418 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3419 data, "\r\n"); st.hasMoreTokens();)
3422 String s = st.nextToken();
3423 if (s.startsWith("#"))
3425 // the line is a comment (as per the RFC 2483)
3428 java.net.URI uri = new java.net.URI(s);
3429 if (uri.getScheme().toLowerCase().startsWith("http"))
3431 protocols.add(DataSourceType.URL);
3432 files.add(uri.toString());
3436 // otherwise preserve old behaviour: catch all for file objects
3437 java.io.File file = new java.io.File(uri);
3438 protocols.add(DataSourceType.FILE);
3439 files.add(file.toString());
3444 if (Cache.log.isDebugEnabled())
3446 if (data == null || !added)
3449 if (t.getTransferDataFlavors() != null
3450 && t.getTransferDataFlavors().length > 0)
3453 "Couldn't resolve drop data. Here are the supported flavors:");
3454 for (DataFlavor fl : t.getTransferDataFlavors())
3457 "Supported transfer dataflavor: " + fl.toString());
3458 Object df = t.getTransferData(fl);
3461 Cache.log.debug("Retrieves: " + df);
3465 Cache.log.debug("Retrieved nothing");
3471 Cache.log.debug("Couldn't resolve dataflavor for drop: "
3477 if (Platform.isWindows())
3480 Cache.log.debug("Scanning dropped content for Windows Link Files");
3482 // resolve any .lnk files in the file drop
3483 for (int f = 0; f < files.size(); f++)
3485 String source = files.get(f).toLowerCase();
3486 if (protocols.get(f).equals(DataSourceType.FILE)
3487 && (source.endsWith(".lnk") || source.endsWith(".url")
3488 || source.endsWith(".site")))
3491 File lf = new File(files.get(f));
3492 // process link file to get a URL
3493 Cache.log.debug("Found potential link file: " + lf);
3494 WindowsShortcut wscfile = new WindowsShortcut(lf);
3495 String fullname = wscfile.getRealFilename();
3496 protocols.set(f, FormatAdapter.checkProtocol(fullname));
3497 files.set(f, fullname);
3498 Cache.log.debug("Parsed real filename " + fullname
3499 + " to extract protocol: " + protocols.get(f));
3501 catch (Exception ex)
3503 Cache.log.error("Couldn't parse "+files.get(f)+" as a link file.",ex);
3511 * Sets the Preferences property for experimental features to True or False
3512 * depending on the state of the controlling menu item
3515 protected void showExperimental_actionPerformed(boolean selected)
3517 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
3521 * Answers a (possibly empty) list of any structure viewer frames (currently
3522 * for either Jmol or Chimera) which are currently open. This may optionally
3523 * be restricted to viewers of a specified class, or viewers linked to a
3524 * specified alignment panel.
3527 * if not null, only return viewers linked to this panel
3528 * @param structureViewerClass
3529 * if not null, only return viewers of this class
3532 public List<StructureViewerBase> getStructureViewers(
3533 AlignmentPanel apanel,
3534 Class<? extends StructureViewerBase> structureViewerClass)
3536 List<StructureViewerBase> result = new ArrayList<>();
3537 JInternalFrame[] frames = Desktop.instance.getAllFrames();
3539 for (JInternalFrame frame : frames)
3541 if (frame instanceof StructureViewerBase)
3543 if (structureViewerClass == null
3544 || structureViewerClass.isInstance(frame))
3547 || ((StructureViewerBase) frame).isLinkedWith(apanel))
3549 result.add((StructureViewerBase) frame);