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);
1946 jalview.gui.VamsasApplication v_client = null;
1949 public void vamsasImport_actionPerformed(ActionEvent e)
1951 if (v_client == null)
1953 // Load and try to start a session.
1954 JalviewFileChooser chooser = new JalviewFileChooser(
1955 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1957 chooser.setFileView(new JalviewFileView());
1958 chooser.setDialogTitle(
1959 MessageManager.getString("label.open_saved_vamsas_session"));
1960 chooser.setToolTipText(MessageManager.getString(
1961 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1963 int value = chooser.showOpenDialog(this);
1965 if (value == JalviewFileChooser.APPROVE_OPTION)
1967 String fle = chooser.getSelectedFile().toString();
1968 if (!vamsasImport(chooser.getSelectedFile()))
1970 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1971 MessageManager.formatMessage(
1972 "label.couldnt_import_as_vamsas_session",
1976 .getString("label.vamsas_document_import_failed"),
1977 JvOptionPane.ERROR_MESSAGE);
1983 jalview.bin.Cache.log.error(
1984 "Implementation error - load session from a running session is not supported.");
1989 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1992 * @return true if import was a success and a session was started.
1994 public boolean vamsasImport(URL url)
1996 // TODO: create progress bar
1997 if (v_client != null)
2000 jalview.bin.Cache.log.error(
2001 "Implementation error - load session from a running session is not supported.");
2007 // copy the URL content to a temporary local file
2008 // TODO: be a bit cleverer here with nio (?!)
2009 File file = File.createTempFile("vdocfromurl", ".vdj");
2010 FileOutputStream fos = new FileOutputStream(file);
2011 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2012 byte[] buffer = new byte[2048];
2014 while ((ln = bis.read(buffer)) > -1)
2016 fos.write(buffer, 0, ln);
2020 v_client = new jalview.gui.VamsasApplication(this, file,
2021 url.toExternalForm());
2022 } catch (Exception ex)
2024 jalview.bin.Cache.log.error(
2025 "Failed to create new vamsas session from contents of URL "
2030 setupVamsasConnectedGui();
2031 v_client.initial_update(); // TODO: thread ?
2032 return v_client.inSession();
2036 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2039 * @return true if import was a success and a session was started.
2041 public boolean vamsasImport(File file)
2043 if (v_client != null)
2046 jalview.bin.Cache.log.error(
2047 "Implementation error - load session from a running session is not supported.");
2051 setProgressBar(MessageManager.formatMessage(
2052 "status.importing_vamsas_session_from", new Object[]
2053 { file.getName() }), file.hashCode());
2056 v_client = new jalview.gui.VamsasApplication(this, file, null);
2057 } catch (Exception ex)
2059 setProgressBar(MessageManager.formatMessage(
2060 "status.importing_vamsas_session_from", new Object[]
2061 { file.getName() }), file.hashCode());
2062 jalview.bin.Cache.log.error(
2063 "New vamsas session from existing session file failed:", ex);
2066 setupVamsasConnectedGui();
2067 v_client.initial_update(); // TODO: thread ?
2068 setProgressBar(MessageManager.formatMessage(
2069 "status.importing_vamsas_session_from", new Object[]
2070 { file.getName() }), file.hashCode());
2071 return v_client.inSession();
2074 public boolean joinVamsasSession(String mysesid)
2076 if (v_client != null)
2078 throw new Error(MessageManager
2079 .getString("error.try_join_vamsas_session_another"));
2081 if (mysesid == null)
2084 MessageManager.getString("error.invalid_vamsas_session_id"));
2086 v_client = new VamsasApplication(this, mysesid);
2087 setupVamsasConnectedGui();
2088 v_client.initial_update();
2089 return (v_client.inSession());
2093 public void vamsasStart_actionPerformed(ActionEvent e)
2095 if (v_client == null)
2098 // we just start a default session for moment.
2100 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2101 * getProperty("LAST_DIRECTORY"));
2103 * chooser.setFileView(new JalviewFileView());
2104 * chooser.setDialogTitle("Load Vamsas file");
2105 * chooser.setToolTipText("Import");
2107 * int value = chooser.showOpenDialog(this);
2109 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2110 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2112 v_client = new VamsasApplication(this);
2113 setupVamsasConnectedGui();
2114 v_client.initial_update(); // TODO: thread ?
2118 // store current data in session.
2119 v_client.push_update(); // TODO: thread
2123 protected void setupVamsasConnectedGui()
2125 vamsasStart.setText(MessageManager.getString("label.session_update"));
2126 vamsasSave.setVisible(true);
2127 vamsasStop.setVisible(true);
2128 vamsasImport.setVisible(false); // Document import to existing session is
2129 // not possible for vamsas-client-1.0.
2132 protected void setupVamsasDisconnectedGui()
2134 vamsasSave.setVisible(false);
2135 vamsasStop.setVisible(false);
2136 vamsasImport.setVisible(true);
2138 .setText(MessageManager.getString("label.new_vamsas_session"));
2142 public void vamsasStop_actionPerformed(ActionEvent e)
2144 if (v_client != null)
2146 v_client.end_session();
2148 setupVamsasDisconnectedGui();
2152 protected void buildVamsasStMenu()
2154 if (v_client == null)
2156 String[] sess = null;
2159 sess = VamsasApplication.getSessionList();
2160 } catch (Exception e)
2162 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2168 jalview.bin.Cache.log.debug(
2169 "Got current sessions list: " + sess.length + " entries.");
2170 VamsasStMenu.removeAll();
2171 for (int i = 0; i < sess.length; i++)
2173 JMenuItem sessit = new JMenuItem();
2174 sessit.setText(sess[i]);
2175 sessit.setToolTipText(MessageManager
2176 .formatMessage("label.connect_to_session", new Object[]
2178 final Desktop dsktp = this;
2179 final String mysesid = sess[i];
2180 sessit.addActionListener(new ActionListener()
2184 public void actionPerformed(ActionEvent e)
2186 if (dsktp.v_client == null)
2188 Thread rthr = new Thread(new Runnable()
2194 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2195 dsktp.setupVamsasConnectedGui();
2196 dsktp.v_client.initial_update();
2204 VamsasStMenu.add(sessit);
2206 // don't show an empty menu.
2207 VamsasStMenu.setVisible(sess.length > 0);
2212 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2213 VamsasStMenu.removeAll();
2214 VamsasStMenu.setVisible(false);
2219 // Not interested in the content. Just hide ourselves.
2220 VamsasStMenu.setVisible(false);
2225 public void vamsasSave_actionPerformed(ActionEvent e)
2227 if (v_client != null)
2229 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2230 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2233 chooser.setFileView(new JalviewFileView());
2234 chooser.setDialogTitle(MessageManager
2235 .getString("label.save_vamsas_document_archive"));
2237 int value = chooser.showSaveDialog(this);
2239 if (value == JalviewFileChooser.APPROVE_OPTION)
2241 java.io.File choice = chooser.getSelectedFile();
2242 JPanel progpanel = addProgressPanel(MessageManager
2243 .formatMessage("label.saving_vamsas_doc", new Object[]
2244 { choice.getName() }));
2245 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2246 String warnmsg = null;
2247 String warnttl = null;
2250 v_client.vclient.storeDocument(choice);
2253 warnttl = "Serious Problem saving Vamsas Document";
2254 warnmsg = ex.toString();
2255 jalview.bin.Cache.log
2256 .error("Error Whilst saving document to " + choice, ex);
2258 } catch (Exception ex)
2260 warnttl = "Problem saving Vamsas Document.";
2261 warnmsg = ex.toString();
2262 jalview.bin.Cache.log.warn(
2263 "Exception Whilst saving document to " + choice, ex);
2266 removeProgressPanel(progpanel);
2267 if (warnmsg != null)
2269 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2271 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2277 JPanel vamUpdate = null;
2280 * hide vamsas user gui bits when a vamsas document event is being handled.
2283 * true to hide gui, false to reveal gui
2285 public void setVamsasUpdate(boolean b)
2287 Cache.log.debug("Setting gui for Vamsas update "
2288 + (b ? "in progress" : "finished"));
2290 if (vamUpdate != null)
2292 this.removeProgressPanel(vamUpdate);
2296 vamUpdate = this.addProgressPanel(
2297 MessageManager.getString("label.updating_vamsas_session"));
2299 vamsasStart.setVisible(!b);
2300 vamsasStop.setVisible(!b);
2301 vamsasSave.setVisible(!b);
2304 public JInternalFrame[] getAllFrames()
2306 return desktop.getAllFrames();
2310 * Checks the given url to see if it gives a response indicating that the user
2311 * should be informed of a new questionnaire.
2315 public void checkForQuestionnaire(String url)
2317 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2318 // javax.swing.SwingUtilities.invokeLater(jvq);
2319 new Thread(jvq).start();
2322 public void checkURLLinks()
2324 // Thread off the URL link checker
2325 addDialogThread(new Runnable()
2330 if (Cache.getDefault("CHECKURLLINKS", true))
2332 // check what the actual links are - if it's just the default don't
2333 // bother with the warning
2334 List<String> links = Preferences.sequenceUrlLinks
2337 // only need to check links if there is one with a
2338 // SEQUENCE_ID which is not the default EMBL_EBI link
2339 ListIterator<String> li = links.listIterator();
2340 boolean check = false;
2341 List<JLabel> urls = new ArrayList<>();
2342 while (li.hasNext())
2344 String link = li.next();
2345 if (link.contains(SEQUENCE_ID)
2346 && !UrlConstants.isDefaultString(link))
2349 int barPos = link.indexOf("|");
2350 String urlMsg = barPos == -1 ? link
2351 : link.substring(0, barPos) + ": "
2352 + link.substring(barPos + 1);
2353 urls.add(new JLabel(urlMsg));
2361 // ask user to check in case URL links use old style tokens
2362 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2363 JPanel msgPanel = new JPanel();
2364 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2365 msgPanel.add(Box.createVerticalGlue());
2366 JLabel msg = new JLabel(MessageManager
2367 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2368 JLabel msg2 = new JLabel(MessageManager
2369 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2371 for (JLabel url : urls)
2377 final JCheckBox jcb = new JCheckBox(
2378 MessageManager.getString("label.do_not_display_again"));
2379 jcb.addActionListener(new ActionListener()
2382 public void actionPerformed(ActionEvent e)
2384 // update Cache settings for "don't show this again"
2385 boolean showWarningAgain = !jcb.isSelected();
2386 Cache.setProperty("CHECKURLLINKS",
2387 Boolean.valueOf(showWarningAgain).toString());
2392 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2394 .getString("label.SEQUENCE_ID_no_longer_used"),
2395 JvOptionPane.WARNING_MESSAGE);
2402 * Proxy class for JDesktopPane which optionally displays the current memory
2403 * usage and highlights the desktop area with a red bar if free memory runs
2408 public class MyDesktopPane extends JDesktopPane implements Runnable
2411 private static final float ONE_MB = 1048576f;
2413 boolean showMemoryUsage = false;
2417 java.text.NumberFormat df;
2419 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2422 public MyDesktopPane(boolean showMemoryUsage)
2424 showMemoryUsage(showMemoryUsage);
2427 public void showMemoryUsage(boolean showMemory)
2429 this.showMemoryUsage = showMemory;
2432 Thread worker = new Thread(this);
2438 public boolean isShowMemoryUsage()
2440 return showMemoryUsage;
2446 df = java.text.NumberFormat.getNumberInstance();
2447 df.setMaximumFractionDigits(2);
2448 runtime = Runtime.getRuntime();
2450 while (showMemoryUsage)
2454 maxMemory = runtime.maxMemory() / ONE_MB;
2455 allocatedMemory = runtime.totalMemory() / ONE_MB;
2456 freeMemory = runtime.freeMemory() / ONE_MB;
2457 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2459 percentUsage = (totalFreeMemory / maxMemory) * 100;
2461 // if (percentUsage < 20)
2463 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2465 // instance.set.setBorder(border1);
2468 // sleep after showing usage
2470 } catch (Exception ex)
2472 ex.printStackTrace();
2478 public void paintComponent(Graphics g)
2480 if (showMemoryUsage && g != null && df != null)
2482 if (percentUsage < 20)
2484 g.setColor(Color.red);
2486 FontMetrics fm = g.getFontMetrics();
2489 g.drawString(MessageManager.formatMessage("label.memory_stats",
2491 { df.format(totalFreeMemory), df.format(maxMemory),
2492 df.format(percentUsage) }),
2493 10, getHeight() - fm.getHeight());
2501 * Accessor method to quickly get all the AlignmentFrames loaded.
2503 * @return an array of AlignFrame, or null if none found
2505 public static AlignFrame[] getAlignFrames()
2507 if (Jalview.isHeadlessMode())
2509 // Desktop.desktop is null in headless mode
2510 return new AlignFrame[] { Jalview.currentAlignFrame };
2513 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2519 List<AlignFrame> avp = new ArrayList<>();
2521 for (int i = frames.length - 1; i > -1; i--)
2523 if (frames[i] instanceof AlignFrame)
2525 avp.add((AlignFrame) frames[i]);
2527 else if (frames[i] instanceof SplitFrame)
2530 * Also check for a split frame containing an AlignFrame
2532 GSplitFrame sf = (GSplitFrame) frames[i];
2533 if (sf.getTopFrame() instanceof AlignFrame)
2535 avp.add((AlignFrame) sf.getTopFrame());
2537 if (sf.getBottomFrame() instanceof AlignFrame)
2539 avp.add((AlignFrame) sf.getBottomFrame());
2543 if (avp.size() == 0)
2547 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2552 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2556 public GStructureViewer[] getJmols()
2558 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2564 List<GStructureViewer> avp = new ArrayList<>();
2566 for (int i = frames.length - 1; i > -1; i--)
2568 if (frames[i] instanceof AppJmol)
2570 GStructureViewer af = (GStructureViewer) frames[i];
2574 if (avp.size() == 0)
2578 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2583 * Add Groovy Support to Jalview
2586 public void groovyShell_actionPerformed()
2590 openGroovyConsole();
2591 } catch (Exception ex)
2593 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2594 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2596 MessageManager.getString("label.couldnt_create_groovy_shell"),
2597 MessageManager.getString("label.groovy_support_failed"),
2598 JvOptionPane.ERROR_MESSAGE);
2603 * Open the Groovy console
2605 void openGroovyConsole()
2607 if (groovyConsole == null)
2609 groovyConsole = new groovy.ui.Console();
2610 groovyConsole.setVariable("Jalview", this);
2611 groovyConsole.run();
2614 * We allow only one console at a time, so that AlignFrame menu option
2615 * 'Calculate | Run Groovy script' is unambiguous.
2616 * Disable 'Groovy Console', and enable 'Run script', when the console is
2617 * opened, and the reverse when it is closed
2619 Window window = (Window) groovyConsole.getFrame();
2620 window.addWindowListener(new WindowAdapter()
2623 public void windowClosed(WindowEvent e)
2626 * rebind CMD-Q from Groovy Console to Jalview Quit
2629 enableExecuteGroovy(false);
2635 * show Groovy console window (after close and reopen)
2637 ((Window) groovyConsole.getFrame()).setVisible(true);
2640 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2641 * and disable opening a second console
2643 enableExecuteGroovy(true);
2647 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2648 * binding when opened
2650 protected void addQuitHandler()
2652 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2653 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2654 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2656 getRootPane().getActionMap().put("Quit", new AbstractAction()
2659 public void actionPerformed(ActionEvent e)
2667 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2670 * true if Groovy console is open
2672 public void enableExecuteGroovy(boolean enabled)
2675 * disable opening a second Groovy console
2676 * (or re-enable when the console is closed)
2678 groovyShell.setEnabled(!enabled);
2680 AlignFrame[] alignFrames = getAlignFrames();
2681 if (alignFrames != null)
2683 for (AlignFrame af : alignFrames)
2685 af.setGroovyEnabled(enabled);
2691 * Progress bars managed by the IProgressIndicator method.
2693 private Hashtable<Long, JPanel> progressBars;
2695 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2700 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2703 public void setProgressBar(String message, long id)
2705 if (progressBars == null)
2707 progressBars = new Hashtable<>();
2708 progressBarHandlers = new Hashtable<>();
2711 if (progressBars.get(new Long(id)) != null)
2713 JPanel panel = progressBars.remove(new Long(id));
2714 if (progressBarHandlers.contains(new Long(id)))
2716 progressBarHandlers.remove(new Long(id));
2718 removeProgressPanel(panel);
2722 progressBars.put(new Long(id), addProgressPanel(message));
2729 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2730 * jalview.gui.IProgressIndicatorHandler)
2733 public void registerHandler(final long id,
2734 final IProgressIndicatorHandler handler)
2736 if (progressBarHandlers == null
2737 || !progressBars.containsKey(new Long(id)))
2739 throw new Error(MessageManager.getString(
2740 "error.call_setprogressbar_before_registering_handler"));
2742 progressBarHandlers.put(new Long(id), handler);
2743 final JPanel progressPanel = progressBars.get(new Long(id));
2744 if (handler.canCancel())
2746 JButton cancel = new JButton(
2747 MessageManager.getString("action.cancel"));
2748 final IProgressIndicator us = this;
2749 cancel.addActionListener(new ActionListener()
2753 public void actionPerformed(ActionEvent e)
2755 handler.cancelActivity(id);
2756 us.setProgressBar(MessageManager
2757 .formatMessage("label.cancelled_params", new Object[]
2758 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2762 progressPanel.add(cancel, BorderLayout.EAST);
2768 * @return true if any progress bars are still active
2771 public boolean operationInProgress()
2773 if (progressBars != null && progressBars.size() > 0)
2781 * This will return the first AlignFrame holding the given viewport instance.
2782 * It will break if there are more than one AlignFrames viewing a particular
2786 * @return alignFrame for viewport
2788 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2790 if (desktop != null)
2792 AlignmentPanel[] aps = getAlignmentPanels(
2793 viewport.getSequenceSetId());
2794 for (int panel = 0; aps != null && panel < aps.length; panel++)
2796 if (aps[panel] != null && aps[panel].av == viewport)
2798 return aps[panel].alignFrame;
2805 public VamsasApplication getVamsasApplication()
2812 * flag set if jalview GUI is being operated programmatically
2814 private boolean inBatchMode = false;
2817 * check if jalview GUI is being operated programmatically
2819 * @return inBatchMode
2821 public boolean isInBatchMode()
2827 * set flag if jalview GUI is being operated programmatically
2829 * @param inBatchMode
2831 public void setInBatchMode(boolean inBatchMode)
2833 this.inBatchMode = inBatchMode;
2836 public void startServiceDiscovery()
2838 startServiceDiscovery(false);
2841 public void startServiceDiscovery(boolean blocking)
2843 boolean alive = true;
2844 Thread t0 = null, t1 = null, t2 = null;
2845 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2848 // todo: changesupport handlers need to be transferred
2849 if (discoverer == null)
2851 discoverer = new jalview.ws.jws1.Discoverer();
2852 // register PCS handler for desktop.
2853 discoverer.addPropertyChangeListener(changeSupport);
2855 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2856 // until we phase out completely
2857 (t0 = new Thread(discoverer)).start();
2860 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2862 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2863 .startDiscoverer(changeSupport);
2867 // TODO: do rest service discovery
2876 } catch (Exception e)
2879 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2880 || (t3 != null && t3.isAlive())
2881 || (t0 != null && t0.isAlive());
2887 * called to check if the service discovery process completed successfully.
2891 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2893 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2895 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2896 .getErrorMessages();
2899 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2901 if (serviceChangedDialog == null)
2903 // only run if we aren't already displaying one of these.
2904 addDialogThread(serviceChangedDialog = new Runnable()
2911 * JalviewDialog jd =new JalviewDialog() {
2913 * @Override protected void cancelPressed() { // TODO
2914 * Auto-generated method stub
2916 * }@Override protected void okPressed() { // TODO
2917 * Auto-generated method stub
2919 * }@Override protected void raiseClosed() { // TODO
2920 * Auto-generated method stub
2922 * } }; jd.initDialogFrame(new
2923 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2924 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2925 * + " or mis-configured HTTP proxy settings.<br/>" +
2926 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2928 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2929 * ), true, true, "Web Service Configuration Problem", 450,
2932 * jd.waitForInput();
2934 JvOptionPane.showConfirmDialog(Desktop.desktop,
2935 new JLabel("<html><table width=\"450\"><tr><td>"
2936 + ermsg + "</td></tr></table>"
2937 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2938 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2939 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2940 + " Tools->Preferences dialog box to change them.</p></html>"),
2941 "Web Service Configuration Problem",
2942 JvOptionPane.DEFAULT_OPTION,
2943 JvOptionPane.ERROR_MESSAGE);
2944 serviceChangedDialog = null;
2953 "Errors reported by JABA discovery service. Check web services preferences.\n"
2960 private Runnable serviceChangedDialog = null;
2963 * start a thread to open a URL in the configured browser. Pops up a warning
2964 * dialog to the user if there is an exception when calling out to the browser
2969 public static void showUrl(final String url)
2971 showUrl(url, Desktop.instance);
2975 * Like showUrl but allows progress handler to be specified
2979 * (null) or object implementing IProgressIndicator
2981 public static void showUrl(final String url,
2982 final IProgressIndicator progress)
2984 new Thread(new Runnable()
2991 if (progress != null)
2993 progress.setProgressBar(MessageManager
2994 .formatMessage("status.opening_params", new Object[]
2995 { url }), this.hashCode());
2997 jalview.util.BrowserLauncher.openURL(url);
2998 } catch (Exception ex)
3000 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3002 .getString("label.web_browser_not_found_unix"),
3003 MessageManager.getString("label.web_browser_not_found"),
3004 JvOptionPane.WARNING_MESSAGE);
3006 ex.printStackTrace();
3008 if (progress != null)
3010 progress.setProgressBar(null, this.hashCode());
3016 public static WsParamSetManager wsparamManager = null;
3018 public static ParamManager getUserParameterStore()
3020 if (wsparamManager == null)
3022 wsparamManager = new WsParamSetManager();
3024 return wsparamManager;
3028 * static hyperlink handler proxy method for use by Jalview's internal windows
3032 public static void hyperlinkUpdate(HyperlinkEvent e)
3034 if (e.getEventType() == EventType.ACTIVATED)
3039 url = e.getURL().toString();
3040 Desktop.showUrl(url);
3041 } catch (Exception x)
3045 if (Cache.log != null)
3047 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3052 "Couldn't handle string " + url + " as a URL.");
3055 // ignore any exceptions due to dud links.
3062 * single thread that handles display of dialogs to user.
3064 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3067 * flag indicating if dialogExecutor should try to acquire a permit
3069 private volatile boolean dialogPause = true;
3074 private java.util.concurrent.Semaphore block = new Semaphore(0);
3076 private static groovy.ui.Console groovyConsole;
3079 * add another dialog thread to the queue
3083 public void addDialogThread(final Runnable prompter)
3085 dialogExecutor.submit(new Runnable()
3095 } catch (InterruptedException x)
3100 if (instance == null)
3106 SwingUtilities.invokeAndWait(prompter);
3107 } catch (Exception q)
3109 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3115 public void startDialogQueue()
3117 // set the flag so we don't pause waiting for another permit and semaphore
3118 // the current task to begin
3119 dialogPause = false;
3124 protected void snapShotWindow_actionPerformed(ActionEvent e)
3128 ImageMaker im = new jalview.util.ImageMaker(
3129 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3130 getHeight(), of = new File("Jalview_snapshot"
3131 + System.currentTimeMillis() + ".eps"),
3132 "View of desktop", null, 0, false);
3135 paintAll(im.getGraphics());
3137 } catch (Exception q)
3139 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3143 Cache.log.info("Successfully written snapshot to file "
3144 + of.getAbsolutePath());
3148 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3149 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3150 * and location last time the view was expanded (if any). However it does not
3151 * remember the split pane divider location - this is set to match the
3152 * 'exploding' frame.
3156 public void explodeViews(SplitFrame sf)
3158 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3159 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3160 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3162 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3164 int viewCount = topPanels.size();
3171 * Processing in reverse order works, forwards order leaves the first panels
3172 * not visible. I don't know why!
3174 for (int i = viewCount - 1; i >= 0; i--)
3177 * Make new top and bottom frames. These take over the respective
3178 * AlignmentPanel objects, including their AlignmentViewports, so the
3179 * cdna/protein relationships between the viewports is carried over to the
3182 * explodedGeometry holds the (x, y) position of the previously exploded
3183 * SplitFrame, and the (width, height) of the AlignFrame component
3185 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3186 AlignFrame newTopFrame = new AlignFrame(topPanel);
3187 newTopFrame.setSize(oldTopFrame.getSize());
3188 newTopFrame.setVisible(true);
3189 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3190 .getExplodedGeometry();
3191 if (geometry != null)
3193 newTopFrame.setSize(geometry.getSize());
3196 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3197 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3198 newBottomFrame.setSize(oldBottomFrame.getSize());
3199 newBottomFrame.setVisible(true);
3200 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3201 .getExplodedGeometry();
3202 if (geometry != null)
3204 newBottomFrame.setSize(geometry.getSize());
3207 topPanel.av.setGatherViewsHere(false);
3208 bottomPanel.av.setGatherViewsHere(false);
3209 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3211 if (geometry != null)
3213 splitFrame.setLocation(geometry.getLocation());
3215 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3219 * Clear references to the panels (now relocated in the new SplitFrames)
3220 * before closing the old SplitFrame.
3223 bottomPanels.clear();
3228 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3229 * back into the given SplitFrame as additional views. Note that the gathered
3230 * frames may themselves have multiple views.
3234 public void gatherViews(GSplitFrame source)
3237 * special handling of explodedGeometry for a view within a SplitFrame: - it
3238 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3239 * height) of the AlignFrame component
3241 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3242 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3243 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3244 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3245 myBottomFrame.viewport
3246 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3247 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3248 myTopFrame.viewport.setGatherViewsHere(true);
3249 myBottomFrame.viewport.setGatherViewsHere(true);
3250 String topViewId = myTopFrame.viewport.getSequenceSetId();
3251 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3253 JInternalFrame[] frames = desktop.getAllFrames();
3254 for (JInternalFrame frame : frames)
3256 if (frame instanceof SplitFrame && frame != source)
3258 SplitFrame sf = (SplitFrame) frame;
3259 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3260 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3261 boolean gatherThis = false;
3262 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3264 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3265 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3266 if (topViewId.equals(topPanel.av.getSequenceSetId())
3267 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3270 topPanel.av.setGatherViewsHere(false);
3271 bottomPanel.av.setGatherViewsHere(false);
3272 topPanel.av.setExplodedGeometry(
3273 new Rectangle(sf.getLocation(), topFrame.getSize()));
3274 bottomPanel.av.setExplodedGeometry(
3275 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3276 myTopFrame.addAlignmentPanel(topPanel, false);
3277 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3283 topFrame.getAlignPanels().clear();
3284 bottomFrame.getAlignPanels().clear();
3291 * The dust settles...give focus to the tab we did this from.
3293 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3296 public static groovy.ui.Console getGroovyConsole()
3298 return groovyConsole;
3302 * handles the payload of a drag and drop event.
3304 * TODO refactor to desktop utilities class
3307 * - Data source strings extracted from the drop event
3309 * - protocol for each data source extracted from the drop event
3313 * - the payload from the drop event
3316 public static void transferFromDropTarget(List<String> files,
3317 List<DataSourceType> protocols, DropTargetDropEvent evt,
3318 Transferable t) throws Exception
3321 DataFlavor uriListFlavor = new DataFlavor(
3322 "text/uri-list;class=java.lang.String"), urlFlavour = null;
3325 urlFlavour = new DataFlavor(
3326 "application/x-java-url; class=java.net.URL");
3327 } catch (ClassNotFoundException cfe)
3329 Cache.log.debug("Couldn't instantiate the URL dataflavor.", cfe);
3332 if (urlFlavour != null && t.isDataFlavorSupported(urlFlavour))
3337 java.net.URL url = (URL) t.getTransferData(urlFlavour);
3338 // nb: java 8 osx bug https://bugs.openjdk.java.net/browse/JDK-8156099
3339 // means url may be null.
3342 protocols.add(DataSourceType.URL);
3343 files.add(url.toString());
3344 Cache.log.debug("Drop handled as URL dataflavor "
3345 + files.get(files.size() - 1));
3350 if (Platform.isAMac())
3353 "Please ignore plist error - occurs due to problem with java 8 on OSX");
3357 } catch (Throwable ex)
3359 Cache.log.debug("URL drop handler failed.", ex);
3362 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3364 // Works on Windows and MacOSX
3365 Cache.log.debug("Drop handled as javaFileListFlavor");
3366 for (Object file : (List) t
3367 .getTransferData(DataFlavor.javaFileListFlavor))
3369 files.add(((File) file).toString());
3370 protocols.add(DataSourceType.FILE);
3375 // Unix like behaviour
3376 boolean added = false;
3378 if (t.isDataFlavorSupported(uriListFlavor))
3380 Cache.log.debug("Drop handled as uriListFlavor");
3381 // This is used by Unix drag system
3382 data = (String) t.getTransferData(uriListFlavor);
3386 // fallback to text: workaround - on OSX where there's a JVM bug
3387 Cache.log.debug("standard URIListFlavor failed. Trying text");
3388 // try text fallback
3389 DataFlavor textDf = new DataFlavor(
3390 "text/plain;class=java.lang.String");
3391 if (t.isDataFlavorSupported(textDf))
3393 data = (String) t.getTransferData(textDf);
3396 Cache.log.debug("Plain text drop content returned "
3397 + (data == null ? "Null - failed" : data));
3402 while (protocols.size() < files.size())
3404 Cache.log.debug("Adding missing FILE protocol for "
3405 + files.get(protocols.size()));
3406 protocols.add(DataSourceType.FILE);
3408 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3409 data, "\r\n"); st.hasMoreTokens();)
3412 String s = st.nextToken();
3413 if (s.startsWith("#"))
3415 // the line is a comment (as per the RFC 2483)
3418 java.net.URI uri = new java.net.URI(s);
3419 if (uri.getScheme().toLowerCase().startsWith("http"))
3421 protocols.add(DataSourceType.URL);
3422 files.add(uri.toString());
3426 // otherwise preserve old behaviour: catch all for file objects
3427 java.io.File file = new java.io.File(uri);
3428 protocols.add(DataSourceType.FILE);
3429 files.add(file.toString());
3434 if (Cache.log.isDebugEnabled())
3436 if (data == null || !added)
3439 if (t.getTransferDataFlavors() != null
3440 && t.getTransferDataFlavors().length > 0)
3443 "Couldn't resolve drop data. Here are the supported flavors:");
3444 for (DataFlavor fl : t.getTransferDataFlavors())
3447 "Supported transfer dataflavor: " + fl.toString());
3448 Object df = t.getTransferData(fl);
3451 Cache.log.debug("Retrieves: " + df);
3455 Cache.log.debug("Retrieved nothing");
3461 Cache.log.debug("Couldn't resolve dataflavor for drop: "
3467 if (Platform.isWindows())
3470 Cache.log.debug("Scanning dropped content for Windows Link Files");
3472 // resolve any .lnk files in the file drop
3473 for (int f = 0; f < files.size(); f++)
3475 String source = files.get(f).toLowerCase();
3476 if (protocols.get(f).equals(DataSourceType.FILE)
3477 && (source.endsWith(".lnk") || source.endsWith(".url")
3478 || source.endsWith(".site")))
3481 File lf = new File(files.get(f));
3482 // process link file to get a URL
3483 Cache.log.debug("Found potential link file: " + lf);
3484 WindowsShortcut wscfile = new WindowsShortcut(lf);
3485 String fullname = wscfile.getRealFilename();
3486 protocols.set(f, FormatAdapter.checkProtocol(fullname));
3487 files.set(f, fullname);
3488 Cache.log.debug("Parsed real filename " + fullname
3489 + " to extract protocol: " + protocols.get(f));
3491 catch (Exception ex)
3493 Cache.log.error("Couldn't parse "+files.get(f)+" as a link file.",ex);
3501 * Sets the Preferences property for experimental features to True or False
3502 * depending on the state of the controlling menu item
3505 protected void showExperimental_actionPerformed(boolean selected)
3507 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
3511 * Answers a (possibly empty) list of any structure viewer frames (currently
3512 * for either Jmol or Chimera) which are currently open. This may optionally
3513 * be restricted to viewers of a specified class, or viewers linked to a
3514 * specified alignment panel.
3517 * if not null, only return viewers linked to this panel
3518 * @param structureViewerClass
3519 * if not null, only return viewers of this class
3522 public List<StructureViewerBase> getStructureViewers(
3523 AlignmentPanel apanel,
3524 Class<? extends StructureViewerBase> structureViewerClass)
3526 List<StructureViewerBase> result = new ArrayList<>();
3527 JInternalFrame[] frames = Desktop.instance.getAllFrames();
3529 for (JInternalFrame frame : frames)
3531 if (frame instanceof StructureViewerBase)
3533 if (structureViewerClass == null
3534 || structureViewerClass.isInstance(frame))
3537 || ((StructureViewerBase) frame).isLinkedWith(apanel))
3539 result.add((StructureViewerBase) frame);