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.InputEvent;
73 import java.awt.event.KeyEvent;
74 import java.awt.event.MouseAdapter;
75 import java.awt.event.MouseEvent;
76 import java.awt.event.WindowAdapter;
77 import java.awt.event.WindowEvent;
78 import java.beans.PropertyChangeEvent;
79 import java.beans.PropertyChangeListener;
80 import java.io.BufferedInputStream;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Hashtable;
87 import java.util.List;
88 import java.util.ListIterator;
89 import java.util.StringTokenizer;
90 import java.util.Vector;
91 import java.util.concurrent.ExecutorService;
92 import java.util.concurrent.Executors;
93 import java.util.concurrent.Semaphore;
95 import javax.swing.AbstractAction;
96 import javax.swing.Action;
97 import javax.swing.ActionMap;
98 import javax.swing.Box;
99 import javax.swing.BoxLayout;
100 import javax.swing.DefaultDesktopManager;
101 import javax.swing.DesktopManager;
102 import javax.swing.InputMap;
103 import javax.swing.JButton;
104 import javax.swing.JCheckBox;
105 import javax.swing.JComboBox;
106 import javax.swing.JComponent;
107 import javax.swing.JDesktopPane;
108 import javax.swing.JFrame;
109 import javax.swing.JInternalFrame;
110 import javax.swing.JLabel;
111 import javax.swing.JMenuItem;
112 import javax.swing.JPanel;
113 import javax.swing.JPopupMenu;
114 import javax.swing.JProgressBar;
115 import javax.swing.KeyStroke;
116 import javax.swing.SwingUtilities;
117 import javax.swing.event.HyperlinkEvent;
118 import javax.swing.event.HyperlinkEvent.EventType;
119 import javax.swing.event.InternalFrameAdapter;
120 import javax.swing.event.InternalFrameEvent;
121 import javax.swing.event.MenuEvent;
122 import javax.swing.event.MenuListener;
124 import org.stackoverflowusers.file.WindowsShortcut;
131 * @version $Revision: 1.155 $
133 public class Desktop extends jalview.jbgui.GDesktop
134 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
135 jalview.api.StructureSelectionManagerProvider
137 private static int DEFAULT_MIN_WIDTH = 300;
139 private static int DEFAULT_MIN_HEIGHT = 250;
141 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
143 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
145 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
147 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
150 * news reader - null if it was never started.
152 private BlogReader jvnews = null;
154 private File projectFile;
158 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
160 public void addJalviewPropertyChangeListener(
161 PropertyChangeListener listener)
163 changeSupport.addJalviewPropertyChangeListener(listener);
167 * @param propertyName
169 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
170 * java.beans.PropertyChangeListener)
172 public void addJalviewPropertyChangeListener(String propertyName,
173 PropertyChangeListener listener)
175 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
179 * @param propertyName
181 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
182 * java.beans.PropertyChangeListener)
184 public void removeJalviewPropertyChangeListener(String propertyName,
185 PropertyChangeListener listener)
187 changeSupport.removeJalviewPropertyChangeListener(propertyName,
191 /** Singleton Desktop instance */
192 public static Desktop instance;
194 public static MyDesktopPane desktop;
196 static int openFrameCount = 0;
198 static final int xOffset = 30;
200 static final int yOffset = 30;
202 public static jalview.ws.jws1.Discoverer discoverer;
204 public static Object[] jalviewClipboard;
206 public static boolean internalCopy = false;
208 static int fileLoadingCount = 0;
210 class MyDesktopManager implements DesktopManager
213 private DesktopManager delegate;
215 public MyDesktopManager(DesktopManager delegate)
217 this.delegate = delegate;
221 public void activateFrame(JInternalFrame f)
225 delegate.activateFrame(f);
226 } catch (NullPointerException npe)
228 Point p = getMousePosition();
229 instance.showPasteMenu(p.x, p.y);
234 public void beginDraggingFrame(JComponent f)
236 delegate.beginDraggingFrame(f);
240 public void beginResizingFrame(JComponent f, int direction)
242 delegate.beginResizingFrame(f, direction);
246 public void closeFrame(JInternalFrame f)
248 delegate.closeFrame(f);
252 public void deactivateFrame(JInternalFrame f)
254 delegate.deactivateFrame(f);
258 public void deiconifyFrame(JInternalFrame f)
260 delegate.deiconifyFrame(f);
264 public void dragFrame(JComponent f, int newX, int newY)
270 delegate.dragFrame(f, newX, newY);
274 public void endDraggingFrame(JComponent f)
276 delegate.endDraggingFrame(f);
281 public void endResizingFrame(JComponent f)
283 delegate.endResizingFrame(f);
288 public void iconifyFrame(JInternalFrame f)
290 delegate.iconifyFrame(f);
294 public void maximizeFrame(JInternalFrame f)
296 delegate.maximizeFrame(f);
300 public void minimizeFrame(JInternalFrame f)
302 delegate.minimizeFrame(f);
306 public void openFrame(JInternalFrame f)
308 delegate.openFrame(f);
312 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
319 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
323 public void setBoundsForFrame(JComponent f, int newX, int newY,
324 int newWidth, int newHeight)
326 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
329 // All other methods, simply delegate
334 * Creates a new Desktop object.
339 * A note to implementors. It is ESSENTIAL that any activities that might
340 * block are spawned off as threads rather than waited for during this
344 doVamsasClientCheck();
346 doConfigureStructurePrefs();
347 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
348 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
349 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
351 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
353 desktop = new MyDesktopPane(selmemusage);
354 showMemusage.setSelected(selmemusage);
355 desktop.setBackground(Color.white);
356 getContentPane().setLayout(new BorderLayout());
357 // alternate config - have scrollbars - see notes in JAL-153
358 // JScrollPane sp = new JScrollPane();
359 // sp.getViewport().setView(desktop);
360 // getContentPane().add(sp, BorderLayout.CENTER);
361 getContentPane().add(desktop, BorderLayout.CENTER);
362 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
364 // This line prevents Windows Look&Feel resizing all new windows to maximum
365 // if previous window was maximised
366 desktop.setDesktopManager(
367 new MyDesktopManager(
368 (Platform.isWindows() ? new DefaultDesktopManager()
370 ? new AquaInternalFrameManager(
371 desktop.getDesktopManager())
372 : desktop.getDesktopManager())));
374 Rectangle dims = getLastKnownDimensions("");
381 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
382 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
385 jconsole = new Console(this, showjconsole);
386 // add essential build information
388 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
389 + "\n" + "Jalview Installation: "
390 + jalview.bin.Cache.getDefault("INSTALLATION",
392 + "\n" + "Build Date: "
393 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
394 + "\n" + "Java version: "
395 + System.getProperty("java.version") + "\n"
396 + System.getProperty("os.arch") + " "
397 + System.getProperty("os.name") + " "
398 + System.getProperty("os.version"));
400 showConsole(showjconsole);
402 showNews.setVisible(false);
404 experimentalFeatures.setSelected(showExperimental());
406 getIdentifiersOrgData();
410 this.addWindowListener(new WindowAdapter()
413 public void windowClosing(WindowEvent evt)
420 this.addMouseListener(ma = new MouseAdapter()
423 public void mousePressed(MouseEvent evt)
425 if (evt.isPopupTrigger()) // Mac
427 showPasteMenu(evt.getX(), evt.getY());
432 public void mouseReleased(MouseEvent evt)
434 if (evt.isPopupTrigger()) // Windows
436 showPasteMenu(evt.getX(), evt.getY());
440 desktop.addMouseListener(ma);
442 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
443 // Spawn a thread that shows the splashscreen
444 SwingUtilities.invokeLater(new Runnable()
453 // Thread off a new instance of the file chooser - this reduces the time it
454 // takes to open it later on.
455 new Thread(new Runnable()
460 Cache.log.debug("Filechooser init thread started.");
461 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
462 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
464 Cache.log.debug("Filechooser init thread finished.");
467 // Add the service change listener
468 changeSupport.addJalviewPropertyChangeListener("services",
469 new PropertyChangeListener()
473 public void propertyChange(PropertyChangeEvent evt)
475 Cache.log.debug("Firing service changed event for "
476 + evt.getNewValue());
477 JalviewServicesChanged(evt);
484 * Answers true if user preferences to enable experimental features is True
489 public boolean showExperimental()
491 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
492 Boolean.FALSE.toString());
493 return Boolean.valueOf(experimental).booleanValue();
496 public void doConfigureStructurePrefs()
498 // configure services
499 StructureSelectionManager ssm = StructureSelectionManager
500 .getStructureSelectionManager(this);
501 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
503 ssm.setAddTempFacAnnot(jalview.bin.Cache
504 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
505 ssm.setProcessSecondaryStructure(jalview.bin.Cache
506 .getDefault(Preferences.STRUCT_FROM_PDB, true));
507 ssm.setSecStructServices(
508 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
512 ssm.setAddTempFacAnnot(false);
513 ssm.setProcessSecondaryStructure(false);
514 ssm.setSecStructServices(false);
518 public void checkForNews()
520 final Desktop me = this;
521 // Thread off the news reader, in case there are connection problems.
522 new Thread(new Runnable()
527 Cache.log.debug("Starting news thread.");
529 jvnews = new BlogReader(me);
530 showNews.setVisible(true);
531 Cache.log.debug("Completed news thread.");
536 public void getIdentifiersOrgData()
538 // Thread off the identifiers fetcher
539 new Thread(new Runnable()
544 Cache.log.debug("Downloading data from identifiers.org");
545 UrlDownloadClient client = new UrlDownloadClient();
548 client.download(IdOrgSettings.getUrl(),
549 IdOrgSettings.getDownloadLocation());
550 } catch (IOException e)
552 Cache.log.debug("Exception downloading identifiers.org data"
561 protected void showNews_actionPerformed(ActionEvent e)
563 showNews(showNews.isSelected());
566 void showNews(boolean visible)
569 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
570 showNews.setSelected(visible);
571 if (visible && !jvnews.isVisible())
573 new Thread(new Runnable()
578 long now = System.currentTimeMillis();
579 Desktop.instance.setProgressBar(
580 MessageManager.getString("status.refreshing_news"),
582 jvnews.refreshNews();
583 Desktop.instance.setProgressBar(null, now);
592 * recover the last known dimensions for a jalview window
595 * - empty string is desktop, all other windows have unique prefix
596 * @return null or last known dimensions scaled to current geometry (if last
597 * window geom was known)
599 Rectangle getLastKnownDimensions(String windowName)
601 // TODO: lock aspect ratio for scaling desktop Bug #0058199
602 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
603 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
604 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
605 String width = jalview.bin.Cache
606 .getProperty(windowName + "SCREEN_WIDTH");
607 String height = jalview.bin.Cache
608 .getProperty(windowName + "SCREEN_HEIGHT");
609 if ((x != null) && (y != null) && (width != null) && (height != null))
611 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
612 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
613 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
615 // attempt #1 - try to cope with change in screen geometry - this
616 // version doesn't preserve original jv aspect ratio.
617 // take ratio of current screen size vs original screen size.
618 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
619 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
620 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
621 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
622 // rescale the bounds depending upon the current screen geometry.
623 ix = (int) (ix * sw);
624 iw = (int) (iw * sw);
625 iy = (int) (iy * sh);
626 ih = (int) (ih * sh);
627 while (ix >= screenSize.width)
629 jalview.bin.Cache.log.debug(
630 "Window geometry location recall error: shifting horizontal to within screenbounds.");
631 ix -= screenSize.width;
633 while (iy >= screenSize.height)
635 jalview.bin.Cache.log.debug(
636 "Window geometry location recall error: shifting vertical to within screenbounds.");
637 iy -= screenSize.height;
639 jalview.bin.Cache.log.debug(
640 "Got last known dimensions for " + windowName + ": x:" + ix
641 + " y:" + iy + " width:" + iw + " height:" + ih);
643 // return dimensions for new instance
644 return new Rectangle(ix, iy, iw, ih);
649 private void doVamsasClientCheck()
651 if (jalview.bin.Cache.vamsasJarsPresent())
653 setupVamsasDisconnectedGui();
654 VamsasMenu.setVisible(true);
655 final Desktop us = this;
656 VamsasMenu.addMenuListener(new MenuListener()
658 // this listener remembers when the menu was first selected, and
659 // doesn't rebuild the session list until it has been cleared and
661 boolean refresh = true;
664 public void menuCanceled(MenuEvent e)
670 public void menuDeselected(MenuEvent e)
676 public void menuSelected(MenuEvent e)
680 us.buildVamsasStMenu();
685 vamsasStart.setVisible(true);
689 void showPasteMenu(int x, int y)
691 JPopupMenu popup = new JPopupMenu();
692 JMenuItem item = new JMenuItem(
693 MessageManager.getString("label.paste_new_window"));
694 item.addActionListener(new ActionListener()
697 public void actionPerformed(ActionEvent evt)
704 popup.show(this, x, y);
711 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
712 Transferable contents = c.getContents(this);
714 if (contents != null)
716 String file = (String) contents
717 .getTransferData(DataFlavor.stringFlavor);
719 FileFormatI format = new IdentifyFile().identify(file,
720 DataSourceType.PASTE);
722 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
725 } catch (Exception ex)
728 "Unable to paste alignment from system clipboard:\n" + ex);
733 * Adds and opens the given frame to the desktop
744 public static synchronized void addInternalFrame(
745 final JInternalFrame frame, String title, int w, int h)
747 addInternalFrame(frame, title, true, w, h, true, false);
751 * Add an internal frame to the Jalview desktop
758 * When true, display frame immediately, otherwise, caller must call
759 * setVisible themselves.
765 public static synchronized void addInternalFrame(
766 final JInternalFrame frame, String title, boolean makeVisible,
769 addInternalFrame(frame, title, makeVisible, w, h, true, false);
773 * Add an internal frame to the Jalview desktop and make it visible
786 public static synchronized void addInternalFrame(
787 final JInternalFrame frame, String title, int w, int h,
790 addInternalFrame(frame, title, true, w, h, resizable, false);
794 * Add an internal frame to the Jalview desktop
801 * When true, display frame immediately, otherwise, caller must call
802 * setVisible themselves.
809 * @param ignoreMinSize
810 * Do not set the default minimum size for frame
812 public static synchronized void addInternalFrame(
813 final JInternalFrame frame, String title, boolean makeVisible,
814 int w, int h, boolean resizable, boolean ignoreMinSize)
817 // TODO: allow callers to determine X and Y position of frame (eg. via
819 // TODO: consider fixing method to update entries in the window submenu with
820 // the current window title
822 frame.setTitle(title);
823 if (frame.getWidth() < 1 || frame.getHeight() < 1)
827 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
828 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
829 // IF JALVIEW IS RUNNING HEADLESS
830 // ///////////////////////////////////////////////
831 if (instance == null || (System.getProperty("java.awt.headless") != null
832 && System.getProperty("java.awt.headless").equals("true")))
841 frame.setMinimumSize(
842 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
844 // Set default dimension for Alignment Frame window.
845 // The Alignment Frame window could be added from a number of places,
847 // I did this here in order not to miss out on any Alignment frame.
848 if (frame instanceof AlignFrame)
850 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
851 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
855 frame.setVisible(makeVisible);
856 frame.setClosable(true);
857 frame.setResizable(resizable);
858 frame.setMaximizable(resizable);
859 frame.setIconifiable(resizable);
860 frame.setOpaque(false);
862 if (frame.getX() < 1 && frame.getY() < 1)
864 frame.setLocation(xOffset * openFrameCount,
865 yOffset * ((openFrameCount - 1) % 10) + yOffset);
869 * add an entry for the new frame in the Window menu
870 * (and remove it when the frame is closed)
872 final JMenuItem menuItem = new JMenuItem(title);
873 frame.addInternalFrameListener(new InternalFrameAdapter()
876 public void internalFrameActivated(InternalFrameEvent evt)
878 JInternalFrame itf = desktop.getSelectedFrame();
881 if (itf instanceof AlignFrame)
883 Jalview.setCurrentAlignFrame((AlignFrame) itf);
890 public void internalFrameClosed(InternalFrameEvent evt)
892 PaintRefresher.RemoveComponent(frame);
895 * defensive check to prevent frames being
896 * added half off the window
898 if (openFrameCount > 0)
904 * ensure no reference to alignFrame retained by menu item listener
906 if (menuItem.getActionListeners().length > 0)
908 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
910 windowMenu.remove(menuItem);
914 menuItem.addActionListener(new ActionListener()
917 public void actionPerformed(ActionEvent e)
921 frame.setSelected(true);
922 frame.setIcon(false);
923 } catch (java.beans.PropertyVetoException ex)
930 setKeyBindings(frame);
934 windowMenu.add(menuItem);
939 frame.setSelected(true);
940 frame.requestFocus();
941 } catch (java.beans.PropertyVetoException ve)
943 } catch (java.lang.ClassCastException cex)
946 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
952 * Add key bindings to a JInternalFrame so that Ctrl-W and Cmd-W will close
957 private static void setKeyBindings(JInternalFrame frame)
959 @SuppressWarnings("serial")
960 final Action closeAction = new AbstractAction()
963 public void actionPerformed(ActionEvent e)
970 * set up key bindings for Ctrl-W and Cmd-W, with the same (Close) action
972 KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
973 InputEvent.CTRL_DOWN_MASK);
974 KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
975 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
977 InputMap inputMap = frame
978 .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
979 String ctrlW = ctrlWKey.toString();
980 inputMap.put(ctrlWKey, ctrlW);
981 inputMap.put(cmdWKey, ctrlW);
983 ActionMap actionMap = frame.getActionMap();
984 actionMap.put(ctrlW, closeAction);
988 public void lostOwnership(Clipboard clipboard, Transferable contents)
992 Desktop.jalviewClipboard = null;
995 internalCopy = false;
999 public void dragEnter(DropTargetDragEvent evt)
1004 public void dragExit(DropTargetEvent evt)
1009 public void dragOver(DropTargetDragEvent evt)
1014 public void dropActionChanged(DropTargetDragEvent evt)
1025 public void drop(DropTargetDropEvent evt)
1027 boolean success = true;
1028 // JAL-1552 - acceptDrop required before getTransferable call for
1029 // Java's Transferable for native dnd
1030 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1031 Transferable t = evt.getTransferable();
1032 List<String> files = new ArrayList<>();
1033 List<DataSourceType> protocols = new ArrayList<>();
1037 Desktop.transferFromDropTarget(files, protocols, evt, t);
1038 } catch (Exception e)
1040 e.printStackTrace();
1048 for (int i = 0; i < files.size(); i++)
1050 String file = files.get(i).toString();
1051 DataSourceType protocol = (protocols == null)
1052 ? DataSourceType.FILE
1054 FileFormatI format = null;
1056 if (file.endsWith(".jar"))
1058 format = FileFormat.Jalview;
1063 format = new IdentifyFile().identify(file, protocol);
1066 new FileLoader().LoadFile(file, protocol, format);
1069 } catch (Exception ex)
1074 evt.dropComplete(success); // need this to ensure input focus is properly
1075 // transfered to any new windows created
1085 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1087 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1088 JalviewFileChooser chooser = JalviewFileChooser
1089 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1091 chooser.setFileView(new JalviewFileView());
1092 chooser.setDialogTitle(
1093 MessageManager.getString("label.open_local_file"));
1094 chooser.setToolTipText(MessageManager.getString("action.open"));
1096 int value = chooser.showOpenDialog(this);
1098 if (value == JalviewFileChooser.APPROVE_OPTION)
1100 String choice = chooser.getSelectedFile().getPath();
1101 Cache.setProperty("LAST_DIRECTORY",
1102 chooser.getSelectedFile().getParent());
1104 FileFormatI format = chooser.getSelectedFormat();
1107 * Call IdentifyFile to verify the file contains what its extension implies.
1108 * Skip this step for dynamically added file formats, because
1109 * IdentifyFile does not know how to recognise them.
1111 if (FileFormats.getInstance().isIdentifiable(format))
1115 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1116 } catch (FileFormatException e)
1118 // format = null; //??
1122 if (viewport != null)
1124 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1129 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1141 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1143 // This construct allows us to have a wider textfield
1145 JLabel label = new JLabel(
1146 MessageManager.getString("label.input_file_url"));
1147 final JComboBox history = new JComboBox();
1149 JPanel panel = new JPanel(new GridLayout(2, 1));
1152 history.setPreferredSize(new Dimension(400, 20));
1153 history.setEditable(true);
1154 history.addItem("http://www.");
1156 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1160 if (historyItems != null)
1162 st = new StringTokenizer(historyItems, "\t");
1164 while (st.hasMoreTokens())
1166 history.addItem(st.nextElement());
1170 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1171 MessageManager.getString("label.input_alignment_from_url"),
1172 JvOptionPane.OK_CANCEL_OPTION);
1174 if (reply != JvOptionPane.OK_OPTION)
1179 String url = history.getSelectedItem().toString();
1181 if (url.toLowerCase().endsWith(".jar"))
1183 if (viewport != null)
1185 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1186 FileFormat.Jalview);
1190 new FileLoader().LoadFile(url, DataSourceType.URL,
1191 FileFormat.Jalview);
1196 FileFormatI format = null;
1199 format = new IdentifyFile().identify(url, DataSourceType.URL);
1200 } catch (FileFormatException e)
1202 // TODO revise error handling, distinguish between
1203 // URL not found and response not valid
1208 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1209 MessageManager.formatMessage("label.couldnt_locate",
1212 MessageManager.getString("label.url_not_found"),
1213 JvOptionPane.WARNING_MESSAGE);
1218 if (viewport != null)
1220 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1225 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1231 * Opens the CutAndPaste window for the user to paste an alignment in to
1234 * - if not null, the pasted alignment is added to the current
1235 * alignment; if null, to a new alignment window
1238 public void inputTextboxMenuItem_actionPerformed(
1239 AlignmentViewPanel viewPanel)
1241 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1242 cap.setForInput(viewPanel);
1243 Desktop.addInternalFrame(cap,
1244 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1254 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1255 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1257 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1258 screen.height + "");
1259 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1260 getWidth(), getHeight()));
1262 if (jconsole != null)
1264 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1265 jconsole.stopConsole();
1269 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1272 if (dialogExecutor != null)
1274 dialogExecutor.shutdownNow();
1276 closeAll_actionPerformed(null);
1278 if (groovyConsole != null)
1280 // suppress a possible repeat prompt to save script
1281 groovyConsole.setDirty(false);
1282 groovyConsole.exit();
1287 private void storeLastKnownDimensions(String string, Rectangle jc)
1289 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1290 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1291 + " height:" + jc.height);
1293 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1294 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1295 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1296 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1306 public void aboutMenuItem_actionPerformed(ActionEvent e)
1308 // StringBuffer message = getAboutMessage(false);
1309 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1311 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1312 new Thread(new Runnable()
1317 new SplashScreen(true);
1322 public StringBuffer getAboutMessage(boolean shortv)
1324 StringBuffer message = new StringBuffer();
1325 message.append("<html>");
1328 message.append("<h1><strong>Version: "
1329 + jalview.bin.Cache.getProperty("VERSION")
1330 + "</strong></h1>");
1331 message.append("<strong>Last Updated: <em>"
1332 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1333 + "</em></strong>");
1339 message.append("<strong>Version "
1340 + jalview.bin.Cache.getProperty("VERSION")
1341 + "; last updated: "
1342 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1345 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1346 .equals("Checking"))
1348 message.append("<br>...Checking latest version...</br>");
1350 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1351 .equals(jalview.bin.Cache.getProperty("VERSION")))
1353 boolean red = false;
1354 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1355 .indexOf("automated build") == -1)
1358 // Displayed when code version and jnlp version do not match and code
1359 // version is not a development build
1360 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1363 message.append("<br>!! Version "
1364 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1366 + " is available for download from "
1367 + jalview.bin.Cache.getDefault("www.jalview.org",
1368 "http://www.jalview.org")
1372 message.append("</div>");
1375 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1377 "The Jalview Authors (See AUTHORS file for current list)")
1378 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1379 + "<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"
1380 + "<br><br>If you use Jalview, please cite:"
1381 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1382 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1383 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1395 public void documentationMenuItem_actionPerformed(ActionEvent e)
1399 Help.showHelpWindow();
1400 } catch (Exception ex)
1406 public void closeAll_actionPerformed(ActionEvent e)
1408 // TODO show a progress bar while closing?
1409 JInternalFrame[] frames = desktop.getAllFrames();
1410 for (int i = 0; i < frames.length; i++)
1414 frames[i].setClosed(true);
1415 } catch (java.beans.PropertyVetoException ex)
1419 Jalview.setCurrentAlignFrame(null);
1420 System.out.println("ALL CLOSED");
1421 if (v_client != null)
1423 // TODO clear binding to vamsas document objects on close_all
1427 * reset state of singleton objects as appropriate (clear down session state
1428 * when all windows are closed)
1430 StructureSelectionManager ssm = StructureSelectionManager
1431 .getStructureSelectionManager(this);
1439 public void raiseRelated_actionPerformed(ActionEvent e)
1441 reorderAssociatedWindows(false, false);
1445 public void minimizeAssociated_actionPerformed(ActionEvent e)
1447 reorderAssociatedWindows(true, false);
1450 void closeAssociatedWindows()
1452 reorderAssociatedWindows(false, true);
1458 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1462 protected void garbageCollect_actionPerformed(ActionEvent e)
1464 // We simply collect the garbage
1465 jalview.bin.Cache.log.debug("Collecting garbage...");
1467 jalview.bin.Cache.log.debug("Finished garbage collection.");
1474 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1478 protected void showMemusage_actionPerformed(ActionEvent e)
1480 desktop.showMemoryUsage(showMemusage.isSelected());
1487 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1491 protected void showConsole_actionPerformed(ActionEvent e)
1493 showConsole(showConsole.isSelected());
1496 Console jconsole = null;
1499 * control whether the java console is visible or not
1503 void showConsole(boolean selected)
1505 showConsole.setSelected(selected);
1506 // TODO: decide if we should update properties file
1507 Cache.setProperty("SHOW_JAVA_CONSOLE",
1508 Boolean.valueOf(selected).toString());
1509 jconsole.setVisible(selected);
1512 void reorderAssociatedWindows(boolean minimize, boolean close)
1514 JInternalFrame[] frames = desktop.getAllFrames();
1515 if (frames == null || frames.length < 1)
1520 AlignmentViewport source = null, target = null;
1521 if (frames[0] instanceof AlignFrame)
1523 source = ((AlignFrame) frames[0]).getCurrentView();
1525 else if (frames[0] instanceof TreePanel)
1527 source = ((TreePanel) frames[0]).getViewPort();
1529 else if (frames[0] instanceof PCAPanel)
1531 source = ((PCAPanel) frames[0]).av;
1533 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1535 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1540 for (int i = 0; i < frames.length; i++)
1543 if (frames[i] == null)
1547 if (frames[i] instanceof AlignFrame)
1549 target = ((AlignFrame) frames[i]).getCurrentView();
1551 else if (frames[i] instanceof TreePanel)
1553 target = ((TreePanel) frames[i]).getViewPort();
1555 else if (frames[i] instanceof PCAPanel)
1557 target = ((PCAPanel) frames[i]).av;
1559 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1561 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1564 if (source == target)
1570 frames[i].setClosed(true);
1574 frames[i].setIcon(minimize);
1577 frames[i].toFront();
1581 } catch (java.beans.PropertyVetoException ex)
1596 protected void preferences_actionPerformed(ActionEvent e)
1608 public void saveState_actionPerformed(boolean asCastor)
1610 JalviewFileChooser chooser = new JalviewFileChooser(
1611 asCastor ? "jvp" : "jvx",
1614 chooser.setFileView(new JalviewFileView());
1615 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1617 int value = chooser.showSaveDialog(this);
1619 if (value == JalviewFileChooser.APPROVE_OPTION)
1621 final Desktop me = this;
1622 final java.io.File choice = chooser.getSelectedFile();
1623 setProjectFile(choice);
1625 new Thread(new Runnable()
1630 // TODO: refactor to Jalview desktop session controller action.
1631 setProgressBar(MessageManager.formatMessage(
1632 "label.saving_jalview_project", new Object[]
1633 { choice.getName() }), choice.hashCode());
1634 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1635 choice.getParent());
1636 // TODO catch and handle errors for savestate
1637 // TODO prevent user from messing with the Desktop whilst we're saving
1642 new Jalview2XML().saveState(choice);
1646 new jalview.project.Jalview2XML().saveState(choice);
1648 } catch (OutOfMemoryError oom)
1651 "Whilst saving current state to " + choice.getName(),
1653 } catch (Exception ex)
1656 "Problems whilst trying to save to " + choice.getName(),
1658 JvOptionPane.showMessageDialog(me,
1659 MessageManager.formatMessage(
1660 "label.error_whilst_saving_current_state_to",
1662 { choice.getName() }),
1663 MessageManager.getString("label.couldnt_save_project"),
1664 JvOptionPane.WARNING_MESSAGE);
1666 setProgressBar(null, choice.hashCode());
1672 private void setProjectFile(File choice)
1674 this.projectFile = choice;
1677 public File getProjectFile()
1679 return this.projectFile;
1689 public void loadState_actionPerformed(boolean asCastor)
1691 final String[] suffix = asCastor ? new String[] { "jvp", "jar" }
1694 final String[] desc = asCastor
1696 { "Jalview Project", "Jalview Project (old)" }
1698 { "Jalview Project" };
1699 JalviewFileChooser chooser = new JalviewFileChooser(
1700 Cache.getProperty("LAST_DIRECTORY"), suffix,
1703 chooser.setFileView(new JalviewFileView());
1704 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1706 int value = chooser.showOpenDialog(this);
1708 if (value == JalviewFileChooser.APPROVE_OPTION)
1710 final File selectedFile = chooser.getSelectedFile();
1711 setProjectFile(selectedFile);
1712 final String choice = selectedFile.getAbsolutePath();
1713 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1714 new Thread(new Runnable()
1719 setProgressBar(MessageManager.formatMessage(
1720 "label.loading_jalview_project", new Object[]
1721 { choice }), choice.hashCode());
1726 new Jalview2XML().loadJalviewAlign(choice);
1730 new jalview.project.Jalview2XML().loadJalviewAlign(choice);
1732 } catch (OutOfMemoryError oom)
1734 new OOMWarning("Whilst loading project from " + choice, oom);
1735 } catch (Exception ex)
1738 "Problems whilst loading project from " + choice, ex);
1739 JvOptionPane.showMessageDialog(Desktop.desktop,
1740 MessageManager.formatMessage(
1741 "label.error_whilst_loading_project_from",
1744 MessageManager.getString("label.couldnt_load_project"),
1745 JvOptionPane.WARNING_MESSAGE);
1747 setProgressBar(null, choice.hashCode());
1754 public void inputSequence_actionPerformed(ActionEvent e)
1756 new SequenceFetcher(this);
1759 JPanel progressPanel;
1761 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1763 public void startLoading(final String fileName)
1765 if (fileLoadingCount == 0)
1767 fileLoadingPanels.add(addProgressPanel(MessageManager
1768 .formatMessage("label.loading_file", new Object[]
1774 private JPanel addProgressPanel(String string)
1776 if (progressPanel == null)
1778 progressPanel = new JPanel(new GridLayout(1, 1));
1779 totalProgressCount = 0;
1780 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1782 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1783 JProgressBar progressBar = new JProgressBar();
1784 progressBar.setIndeterminate(true);
1786 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1788 thisprogress.add(progressBar, BorderLayout.CENTER);
1789 progressPanel.add(thisprogress);
1790 ((GridLayout) progressPanel.getLayout()).setRows(
1791 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1792 ++totalProgressCount;
1793 instance.validate();
1794 return thisprogress;
1797 int totalProgressCount = 0;
1799 private void removeProgressPanel(JPanel progbar)
1801 if (progressPanel != null)
1803 synchronized (progressPanel)
1805 progressPanel.remove(progbar);
1806 GridLayout gl = (GridLayout) progressPanel.getLayout();
1807 gl.setRows(gl.getRows() - 1);
1808 if (--totalProgressCount < 1)
1810 this.getContentPane().remove(progressPanel);
1811 progressPanel = null;
1818 public void stopLoading()
1821 if (fileLoadingCount < 1)
1823 while (fileLoadingPanels.size() > 0)
1825 removeProgressPanel(fileLoadingPanels.remove(0));
1827 fileLoadingPanels.clear();
1828 fileLoadingCount = 0;
1833 public static int getViewCount(String alignmentId)
1835 AlignmentViewport[] aps = getViewports(alignmentId);
1836 return (aps == null) ? 0 : aps.length;
1841 * @param alignmentId
1842 * - if null, all sets are returned
1843 * @return all AlignmentPanels concerning the alignmentId sequence set
1845 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1847 if (Desktop.desktop == null)
1849 // no frames created and in headless mode
1850 // TODO: verify that frames are recoverable when in headless mode
1853 List<AlignmentPanel> aps = new ArrayList<>();
1854 AlignFrame[] frames = getAlignFrames();
1859 for (AlignFrame af : frames)
1861 for (AlignmentPanel ap : af.alignPanels)
1863 if (alignmentId == null
1864 || alignmentId.equals(ap.av.getSequenceSetId()))
1870 if (aps.size() == 0)
1874 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1879 * get all the viewports on an alignment.
1881 * @param sequenceSetId
1882 * unique alignment id (may be null - all viewports returned in that
1884 * @return all viewports on the alignment bound to sequenceSetId
1886 public static AlignmentViewport[] getViewports(String sequenceSetId)
1888 List<AlignmentViewport> viewp = new ArrayList<>();
1889 if (desktop != null)
1891 AlignFrame[] frames = Desktop.getAlignFrames();
1893 for (AlignFrame afr : frames)
1895 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1896 .equals(sequenceSetId))
1898 if (afr.alignPanels != null)
1900 for (AlignmentPanel ap : afr.alignPanels)
1902 if (sequenceSetId == null
1903 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1911 viewp.add(afr.getViewport());
1915 if (viewp.size() > 0)
1917 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1924 * Explode the views in the given frame into separate AlignFrame
1928 public static void explodeViews(AlignFrame af)
1930 int size = af.alignPanels.size();
1936 for (int i = 0; i < size; i++)
1938 AlignmentPanel ap = af.alignPanels.get(i);
1939 AlignFrame newaf = new AlignFrame(ap);
1942 * Restore the view's last exploded frame geometry if known. Multiple
1943 * views from one exploded frame share and restore the same (frame)
1944 * position and size.
1946 Rectangle geometry = ap.av.getExplodedGeometry();
1947 if (geometry != null)
1949 newaf.setBounds(geometry);
1952 ap.av.setGatherViewsHere(false);
1954 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1955 AlignFrame.DEFAULT_HEIGHT);
1958 af.alignPanels.clear();
1959 af.closeMenuItem_actionPerformed(true);
1964 * Gather expanded views (separate AlignFrame's) with the same sequence set
1965 * identifier back in to this frame as additional views, and close the
1966 * expanded views. Note the expanded frames may themselves have multiple
1967 * views. We take the lot.
1971 public void gatherViews(AlignFrame source)
1973 source.viewport.setGatherViewsHere(true);
1974 source.viewport.setExplodedGeometry(source.getBounds());
1975 JInternalFrame[] frames = desktop.getAllFrames();
1976 String viewId = source.viewport.getSequenceSetId();
1978 for (int t = 0; t < frames.length; t++)
1980 if (frames[t] instanceof AlignFrame && frames[t] != source)
1982 AlignFrame af = (AlignFrame) frames[t];
1983 boolean gatherThis = false;
1984 for (int a = 0; a < af.alignPanels.size(); a++)
1986 AlignmentPanel ap = af.alignPanels.get(a);
1987 if (viewId.equals(ap.av.getSequenceSetId()))
1990 ap.av.setGatherViewsHere(false);
1991 ap.av.setExplodedGeometry(af.getBounds());
1992 source.addAlignmentPanel(ap, false);
1998 af.alignPanels.clear();
1999 af.closeMenuItem_actionPerformed(true);
2006 jalview.gui.VamsasApplication v_client = null;
2009 public void vamsasImport_actionPerformed(ActionEvent e)
2011 if (v_client == null)
2013 // Load and try to start a session.
2014 JalviewFileChooser chooser = new JalviewFileChooser(
2015 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
2017 chooser.setFileView(new JalviewFileView());
2018 chooser.setDialogTitle(
2019 MessageManager.getString("label.open_saved_vamsas_session"));
2020 chooser.setToolTipText(MessageManager.getString(
2021 "label.select_vamsas_session_opened_as_new_vamsas_session"));
2023 int value = chooser.showOpenDialog(this);
2025 if (value == JalviewFileChooser.APPROVE_OPTION)
2027 String fle = chooser.getSelectedFile().toString();
2028 if (!vamsasImport(chooser.getSelectedFile()))
2030 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2031 MessageManager.formatMessage(
2032 "label.couldnt_import_as_vamsas_session",
2036 .getString("label.vamsas_document_import_failed"),
2037 JvOptionPane.ERROR_MESSAGE);
2043 jalview.bin.Cache.log.error(
2044 "Implementation error - load session from a running session is not supported.");
2049 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2052 * @return true if import was a success and a session was started.
2054 public boolean vamsasImport(URL url)
2056 // TODO: create progress bar
2057 if (v_client != null)
2060 jalview.bin.Cache.log.error(
2061 "Implementation error - load session from a running session is not supported.");
2067 // copy the URL content to a temporary local file
2068 // TODO: be a bit cleverer here with nio (?!)
2069 File file = File.createTempFile("vdocfromurl", ".vdj");
2070 FileOutputStream fos = new FileOutputStream(file);
2071 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2072 byte[] buffer = new byte[2048];
2074 while ((ln = bis.read(buffer)) > -1)
2076 fos.write(buffer, 0, ln);
2080 v_client = new jalview.gui.VamsasApplication(this, file,
2081 url.toExternalForm());
2082 } catch (Exception ex)
2084 jalview.bin.Cache.log.error(
2085 "Failed to create new vamsas session from contents of URL "
2090 setupVamsasConnectedGui();
2091 v_client.initial_update(); // TODO: thread ?
2092 return v_client.inSession();
2096 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2099 * @return true if import was a success and a session was started.
2101 public boolean vamsasImport(File file)
2103 if (v_client != null)
2106 jalview.bin.Cache.log.error(
2107 "Implementation error - load session from a running session is not supported.");
2111 setProgressBar(MessageManager.formatMessage(
2112 "status.importing_vamsas_session_from", new Object[]
2113 { file.getName() }), file.hashCode());
2116 v_client = new jalview.gui.VamsasApplication(this, file, null);
2117 } catch (Exception ex)
2119 setProgressBar(MessageManager.formatMessage(
2120 "status.importing_vamsas_session_from", new Object[]
2121 { file.getName() }), file.hashCode());
2122 jalview.bin.Cache.log.error(
2123 "New vamsas session from existing session file failed:", ex);
2126 setupVamsasConnectedGui();
2127 v_client.initial_update(); // TODO: thread ?
2128 setProgressBar(MessageManager.formatMessage(
2129 "status.importing_vamsas_session_from", new Object[]
2130 { file.getName() }), file.hashCode());
2131 return v_client.inSession();
2134 public boolean joinVamsasSession(String mysesid)
2136 if (v_client != null)
2138 throw new Error(MessageManager
2139 .getString("error.try_join_vamsas_session_another"));
2141 if (mysesid == null)
2144 MessageManager.getString("error.invalid_vamsas_session_id"));
2146 v_client = new VamsasApplication(this, mysesid);
2147 setupVamsasConnectedGui();
2148 v_client.initial_update();
2149 return (v_client.inSession());
2153 public void vamsasStart_actionPerformed(ActionEvent e)
2155 if (v_client == null)
2158 // we just start a default session for moment.
2160 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2161 * getProperty("LAST_DIRECTORY"));
2163 * chooser.setFileView(new JalviewFileView());
2164 * chooser.setDialogTitle("Load Vamsas file");
2165 * chooser.setToolTipText("Import");
2167 * int value = chooser.showOpenDialog(this);
2169 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2170 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2172 v_client = new VamsasApplication(this);
2173 setupVamsasConnectedGui();
2174 v_client.initial_update(); // TODO: thread ?
2178 // store current data in session.
2179 v_client.push_update(); // TODO: thread
2183 protected void setupVamsasConnectedGui()
2185 vamsasStart.setText(MessageManager.getString("label.session_update"));
2186 vamsasSave.setVisible(true);
2187 vamsasStop.setVisible(true);
2188 vamsasImport.setVisible(false); // Document import to existing session is
2189 // not possible for vamsas-client-1.0.
2192 protected void setupVamsasDisconnectedGui()
2194 vamsasSave.setVisible(false);
2195 vamsasStop.setVisible(false);
2196 vamsasImport.setVisible(true);
2198 .setText(MessageManager.getString("label.new_vamsas_session"));
2202 public void vamsasStop_actionPerformed(ActionEvent e)
2204 if (v_client != null)
2206 v_client.end_session();
2208 setupVamsasDisconnectedGui();
2212 protected void buildVamsasStMenu()
2214 if (v_client == null)
2216 String[] sess = null;
2219 sess = VamsasApplication.getSessionList();
2220 } catch (Exception e)
2222 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2228 jalview.bin.Cache.log.debug(
2229 "Got current sessions list: " + sess.length + " entries.");
2230 VamsasStMenu.removeAll();
2231 for (int i = 0; i < sess.length; i++)
2233 JMenuItem sessit = new JMenuItem();
2234 sessit.setText(sess[i]);
2235 sessit.setToolTipText(MessageManager
2236 .formatMessage("label.connect_to_session", new Object[]
2238 final Desktop dsktp = this;
2239 final String mysesid = sess[i];
2240 sessit.addActionListener(new ActionListener()
2244 public void actionPerformed(ActionEvent e)
2246 if (dsktp.v_client == null)
2248 Thread rthr = new Thread(new Runnable()
2254 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2255 dsktp.setupVamsasConnectedGui();
2256 dsktp.v_client.initial_update();
2264 VamsasStMenu.add(sessit);
2266 // don't show an empty menu.
2267 VamsasStMenu.setVisible(sess.length > 0);
2272 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2273 VamsasStMenu.removeAll();
2274 VamsasStMenu.setVisible(false);
2279 // Not interested in the content. Just hide ourselves.
2280 VamsasStMenu.setVisible(false);
2285 public void vamsasSave_actionPerformed(ActionEvent e)
2287 if (v_client != null)
2289 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2290 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2293 chooser.setFileView(new JalviewFileView());
2294 chooser.setDialogTitle(MessageManager
2295 .getString("label.save_vamsas_document_archive"));
2297 int value = chooser.showSaveDialog(this);
2299 if (value == JalviewFileChooser.APPROVE_OPTION)
2301 java.io.File choice = chooser.getSelectedFile();
2302 JPanel progpanel = addProgressPanel(MessageManager
2303 .formatMessage("label.saving_vamsas_doc", new Object[]
2304 { choice.getName() }));
2305 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2306 String warnmsg = null;
2307 String warnttl = null;
2310 v_client.vclient.storeDocument(choice);
2313 warnttl = "Serious Problem saving Vamsas Document";
2314 warnmsg = ex.toString();
2315 jalview.bin.Cache.log
2316 .error("Error Whilst saving document to " + choice, ex);
2318 } catch (Exception ex)
2320 warnttl = "Problem saving Vamsas Document.";
2321 warnmsg = ex.toString();
2322 jalview.bin.Cache.log.warn(
2323 "Exception Whilst saving document to " + choice, ex);
2326 removeProgressPanel(progpanel);
2327 if (warnmsg != null)
2329 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2331 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2337 JPanel vamUpdate = null;
2340 * hide vamsas user gui bits when a vamsas document event is being handled.
2343 * true to hide gui, false to reveal gui
2345 public void setVamsasUpdate(boolean b)
2347 Cache.log.debug("Setting gui for Vamsas update "
2348 + (b ? "in progress" : "finished"));
2350 if (vamUpdate != null)
2352 this.removeProgressPanel(vamUpdate);
2356 vamUpdate = this.addProgressPanel(
2357 MessageManager.getString("label.updating_vamsas_session"));
2359 vamsasStart.setVisible(!b);
2360 vamsasStop.setVisible(!b);
2361 vamsasSave.setVisible(!b);
2364 public JInternalFrame[] getAllFrames()
2366 return desktop.getAllFrames();
2370 * Checks the given url to see if it gives a response indicating that the user
2371 * should be informed of a new questionnaire.
2375 public void checkForQuestionnaire(String url)
2377 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2378 // javax.swing.SwingUtilities.invokeLater(jvq);
2379 new Thread(jvq).start();
2382 public void checkURLLinks()
2384 // Thread off the URL link checker
2385 addDialogThread(new Runnable()
2390 if (Cache.getDefault("CHECKURLLINKS", true))
2392 // check what the actual links are - if it's just the default don't
2393 // bother with the warning
2394 List<String> links = Preferences.sequenceUrlLinks
2397 // only need to check links if there is one with a
2398 // SEQUENCE_ID which is not the default EMBL_EBI link
2399 ListIterator<String> li = links.listIterator();
2400 boolean check = false;
2401 List<JLabel> urls = new ArrayList<>();
2402 while (li.hasNext())
2404 String link = li.next();
2405 if (link.contains(SEQUENCE_ID)
2406 && !UrlConstants.isDefaultString(link))
2409 int barPos = link.indexOf("|");
2410 String urlMsg = barPos == -1 ? link
2411 : link.substring(0, barPos) + ": "
2412 + link.substring(barPos + 1);
2413 urls.add(new JLabel(urlMsg));
2421 // ask user to check in case URL links use old style tokens
2422 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2423 JPanel msgPanel = new JPanel();
2424 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2425 msgPanel.add(Box.createVerticalGlue());
2426 JLabel msg = new JLabel(MessageManager
2427 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2428 JLabel msg2 = new JLabel(MessageManager
2429 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2431 for (JLabel url : urls)
2437 final JCheckBox jcb = new JCheckBox(
2438 MessageManager.getString("label.do_not_display_again"));
2439 jcb.addActionListener(new ActionListener()
2442 public void actionPerformed(ActionEvent e)
2444 // update Cache settings for "don't show this again"
2445 boolean showWarningAgain = !jcb.isSelected();
2446 Cache.setProperty("CHECKURLLINKS",
2447 Boolean.valueOf(showWarningAgain).toString());
2452 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2454 .getString("label.SEQUENCE_ID_no_longer_used"),
2455 JvOptionPane.WARNING_MESSAGE);
2462 * Proxy class for JDesktopPane which optionally displays the current memory
2463 * usage and highlights the desktop area with a red bar if free memory runs
2468 public class MyDesktopPane extends JDesktopPane implements Runnable
2471 private static final float ONE_MB = 1048576f;
2473 boolean showMemoryUsage = false;
2477 java.text.NumberFormat df;
2479 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2482 public MyDesktopPane(boolean showMemoryUsage)
2484 showMemoryUsage(showMemoryUsage);
2487 public void showMemoryUsage(boolean showMemory)
2489 this.showMemoryUsage = showMemory;
2492 Thread worker = new Thread(this);
2498 public boolean isShowMemoryUsage()
2500 return showMemoryUsage;
2506 df = java.text.NumberFormat.getNumberInstance();
2507 df.setMaximumFractionDigits(2);
2508 runtime = Runtime.getRuntime();
2510 while (showMemoryUsage)
2514 maxMemory = runtime.maxMemory() / ONE_MB;
2515 allocatedMemory = runtime.totalMemory() / ONE_MB;
2516 freeMemory = runtime.freeMemory() / ONE_MB;
2517 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2519 percentUsage = (totalFreeMemory / maxMemory) * 100;
2521 // if (percentUsage < 20)
2523 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2525 // instance.set.setBorder(border1);
2528 // sleep after showing usage
2530 } catch (Exception ex)
2532 ex.printStackTrace();
2538 public void paintComponent(Graphics g)
2540 if (showMemoryUsage && g != null && df != null)
2542 if (percentUsage < 20)
2544 g.setColor(Color.red);
2546 FontMetrics fm = g.getFontMetrics();
2549 g.drawString(MessageManager.formatMessage("label.memory_stats",
2551 { df.format(totalFreeMemory), df.format(maxMemory),
2552 df.format(percentUsage) }),
2553 10, getHeight() - fm.getHeight());
2561 * Accessor method to quickly get all the AlignmentFrames loaded.
2563 * @return an array of AlignFrame, or null if none found
2565 public static AlignFrame[] getAlignFrames()
2567 if (Jalview.isHeadlessMode())
2569 // Desktop.desktop is null in headless mode
2570 return new AlignFrame[] { Jalview.currentAlignFrame };
2573 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2579 List<AlignFrame> avp = new ArrayList<>();
2581 for (int i = frames.length - 1; i > -1; i--)
2583 if (frames[i] instanceof AlignFrame)
2585 avp.add((AlignFrame) frames[i]);
2587 else if (frames[i] instanceof SplitFrame)
2590 * Also check for a split frame containing an AlignFrame
2592 GSplitFrame sf = (GSplitFrame) frames[i];
2593 if (sf.getTopFrame() instanceof AlignFrame)
2595 avp.add((AlignFrame) sf.getTopFrame());
2597 if (sf.getBottomFrame() instanceof AlignFrame)
2599 avp.add((AlignFrame) sf.getBottomFrame());
2603 if (avp.size() == 0)
2607 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2612 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2616 public GStructureViewer[] getJmols()
2618 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2624 List<GStructureViewer> avp = new ArrayList<>();
2626 for (int i = frames.length - 1; i > -1; i--)
2628 if (frames[i] instanceof AppJmol)
2630 GStructureViewer af = (GStructureViewer) frames[i];
2634 if (avp.size() == 0)
2638 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2643 * Add Groovy Support to Jalview
2646 public void groovyShell_actionPerformed()
2650 openGroovyConsole();
2651 } catch (Exception ex)
2653 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2654 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2656 MessageManager.getString("label.couldnt_create_groovy_shell"),
2657 MessageManager.getString("label.groovy_support_failed"),
2658 JvOptionPane.ERROR_MESSAGE);
2663 * Open the Groovy console
2665 void openGroovyConsole()
2667 if (groovyConsole == null)
2669 groovyConsole = new groovy.ui.Console();
2670 groovyConsole.setVariable("Jalview", this);
2671 groovyConsole.run();
2674 * We allow only one console at a time, so that AlignFrame menu option
2675 * 'Calculate | Run Groovy script' is unambiguous.
2676 * Disable 'Groovy Console', and enable 'Run script', when the console is
2677 * opened, and the reverse when it is closed
2679 Window window = (Window) groovyConsole.getFrame();
2680 window.addWindowListener(new WindowAdapter()
2683 public void windowClosed(WindowEvent e)
2686 * rebind CMD-Q from Groovy Console to Jalview Quit
2689 enableExecuteGroovy(false);
2695 * show Groovy console window (after close and reopen)
2697 ((Window) groovyConsole.getFrame()).setVisible(true);
2700 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2701 * and disable opening a second console
2703 enableExecuteGroovy(true);
2707 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2708 * binding when opened
2710 protected void addQuitHandler()
2712 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2713 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2714 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2716 getRootPane().getActionMap().put("Quit", new AbstractAction()
2719 public void actionPerformed(ActionEvent e)
2727 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2730 * true if Groovy console is open
2732 public void enableExecuteGroovy(boolean enabled)
2735 * disable opening a second Groovy console
2736 * (or re-enable when the console is closed)
2738 groovyShell.setEnabled(!enabled);
2740 AlignFrame[] alignFrames = getAlignFrames();
2741 if (alignFrames != null)
2743 for (AlignFrame af : alignFrames)
2745 af.setGroovyEnabled(enabled);
2751 * Progress bars managed by the IProgressIndicator method.
2753 private Hashtable<Long, JPanel> progressBars;
2755 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2760 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2763 public void setProgressBar(String message, long id)
2765 if (progressBars == null)
2767 progressBars = new Hashtable<>();
2768 progressBarHandlers = new Hashtable<>();
2771 if (progressBars.get(new Long(id)) != null)
2773 JPanel panel = progressBars.remove(new Long(id));
2774 if (progressBarHandlers.contains(new Long(id)))
2776 progressBarHandlers.remove(new Long(id));
2778 removeProgressPanel(panel);
2782 progressBars.put(new Long(id), addProgressPanel(message));
2789 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2790 * jalview.gui.IProgressIndicatorHandler)
2793 public void registerHandler(final long id,
2794 final IProgressIndicatorHandler handler)
2796 if (progressBarHandlers == null
2797 || !progressBars.containsKey(new Long(id)))
2799 throw new Error(MessageManager.getString(
2800 "error.call_setprogressbar_before_registering_handler"));
2802 progressBarHandlers.put(new Long(id), handler);
2803 final JPanel progressPanel = progressBars.get(new Long(id));
2804 if (handler.canCancel())
2806 JButton cancel = new JButton(
2807 MessageManager.getString("action.cancel"));
2808 final IProgressIndicator us = this;
2809 cancel.addActionListener(new ActionListener()
2813 public void actionPerformed(ActionEvent e)
2815 handler.cancelActivity(id);
2816 us.setProgressBar(MessageManager
2817 .formatMessage("label.cancelled_params", new Object[]
2818 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2822 progressPanel.add(cancel, BorderLayout.EAST);
2828 * @return true if any progress bars are still active
2831 public boolean operationInProgress()
2833 if (progressBars != null && progressBars.size() > 0)
2841 * This will return the first AlignFrame holding the given viewport instance.
2842 * It will break if there are more than one AlignFrames viewing a particular
2846 * @return alignFrame for viewport
2848 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2850 if (desktop != null)
2852 AlignmentPanel[] aps = getAlignmentPanels(
2853 viewport.getSequenceSetId());
2854 for (int panel = 0; aps != null && panel < aps.length; panel++)
2856 if (aps[panel] != null && aps[panel].av == viewport)
2858 return aps[panel].alignFrame;
2865 public VamsasApplication getVamsasApplication()
2872 * flag set if jalview GUI is being operated programmatically
2874 private boolean inBatchMode = false;
2877 * check if jalview GUI is being operated programmatically
2879 * @return inBatchMode
2881 public boolean isInBatchMode()
2887 * set flag if jalview GUI is being operated programmatically
2889 * @param inBatchMode
2891 public void setInBatchMode(boolean inBatchMode)
2893 this.inBatchMode = inBatchMode;
2896 public void startServiceDiscovery()
2898 startServiceDiscovery(false);
2901 public void startServiceDiscovery(boolean blocking)
2903 boolean alive = true;
2904 Thread t0 = null, t1 = null, t2 = null;
2905 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2908 // todo: changesupport handlers need to be transferred
2909 if (discoverer == null)
2911 discoverer = new jalview.ws.jws1.Discoverer();
2912 // register PCS handler for desktop.
2913 discoverer.addPropertyChangeListener(changeSupport);
2915 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2916 // until we phase out completely
2917 (t0 = new Thread(discoverer)).start();
2920 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2922 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2923 .startDiscoverer(changeSupport);
2927 // TODO: do rest service discovery
2936 } catch (Exception e)
2939 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2940 || (t3 != null && t3.isAlive())
2941 || (t0 != null && t0.isAlive());
2947 * called to check if the service discovery process completed successfully.
2951 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2953 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2955 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2956 .getErrorMessages();
2959 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2961 if (serviceChangedDialog == null)
2963 // only run if we aren't already displaying one of these.
2964 addDialogThread(serviceChangedDialog = new Runnable()
2971 * JalviewDialog jd =new JalviewDialog() {
2973 * @Override protected void cancelPressed() { // TODO
2974 * Auto-generated method stub
2976 * }@Override protected void okPressed() { // TODO
2977 * Auto-generated method stub
2979 * }@Override protected void raiseClosed() { // TODO
2980 * Auto-generated method stub
2982 * } }; jd.initDialogFrame(new
2983 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2984 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2985 * + " or mis-configured HTTP proxy settings.<br/>" +
2986 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2988 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2989 * ), true, true, "Web Service Configuration Problem", 450,
2992 * jd.waitForInput();
2994 JvOptionPane.showConfirmDialog(Desktop.desktop,
2995 new JLabel("<html><table width=\"450\"><tr><td>"
2996 + ermsg + "</td></tr></table>"
2997 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2998 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2999 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
3000 + " Tools->Preferences dialog box to change them.</p></html>"),
3001 "Web Service Configuration Problem",
3002 JvOptionPane.DEFAULT_OPTION,
3003 JvOptionPane.ERROR_MESSAGE);
3004 serviceChangedDialog = null;
3013 "Errors reported by JABA discovery service. Check web services preferences.\n"
3020 private Runnable serviceChangedDialog = null;
3023 * start a thread to open a URL in the configured browser. Pops up a warning
3024 * dialog to the user if there is an exception when calling out to the browser
3029 public static void showUrl(final String url)
3031 showUrl(url, Desktop.instance);
3035 * Like showUrl but allows progress handler to be specified
3039 * (null) or object implementing IProgressIndicator
3041 public static void showUrl(final String url,
3042 final IProgressIndicator progress)
3044 new Thread(new Runnable()
3051 if (progress != null)
3053 progress.setProgressBar(MessageManager
3054 .formatMessage("status.opening_params", new Object[]
3055 { url }), this.hashCode());
3057 jalview.util.BrowserLauncher.openURL(url);
3058 } catch (Exception ex)
3060 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3062 .getString("label.web_browser_not_found_unix"),
3063 MessageManager.getString("label.web_browser_not_found"),
3064 JvOptionPane.WARNING_MESSAGE);
3066 ex.printStackTrace();
3068 if (progress != null)
3070 progress.setProgressBar(null, this.hashCode());
3076 public static WsParamSetManager wsparamManager = null;
3078 public static ParamManager getUserParameterStore()
3080 if (wsparamManager == null)
3082 wsparamManager = new WsParamSetManager();
3084 return wsparamManager;
3088 * static hyperlink handler proxy method for use by Jalview's internal windows
3092 public static void hyperlinkUpdate(HyperlinkEvent e)
3094 if (e.getEventType() == EventType.ACTIVATED)
3099 url = e.getURL().toString();
3100 Desktop.showUrl(url);
3101 } catch (Exception x)
3105 if (Cache.log != null)
3107 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3112 "Couldn't handle string " + url + " as a URL.");
3115 // ignore any exceptions due to dud links.
3122 * single thread that handles display of dialogs to user.
3124 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3127 * flag indicating if dialogExecutor should try to acquire a permit
3129 private volatile boolean dialogPause = true;
3134 private java.util.concurrent.Semaphore block = new Semaphore(0);
3136 private static groovy.ui.Console groovyConsole;
3139 * add another dialog thread to the queue
3143 public void addDialogThread(final Runnable prompter)
3145 dialogExecutor.submit(new Runnable()
3155 } catch (InterruptedException x)
3160 if (instance == null)
3166 SwingUtilities.invokeAndWait(prompter);
3167 } catch (Exception q)
3169 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3175 public void startDialogQueue()
3177 // set the flag so we don't pause waiting for another permit and semaphore
3178 // the current task to begin
3179 dialogPause = false;
3184 protected void snapShotWindow_actionPerformed(ActionEvent e)
3188 ImageMaker im = new jalview.util.ImageMaker(
3189 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3190 getHeight(), of = new File("Jalview_snapshot"
3191 + System.currentTimeMillis() + ".eps"),
3192 "View of desktop", null, 0, false);
3195 paintAll(im.getGraphics());
3197 } catch (Exception q)
3199 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3203 Cache.log.info("Successfully written snapshot to file "
3204 + of.getAbsolutePath());
3208 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3209 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3210 * and location last time the view was expanded (if any). However it does not
3211 * remember the split pane divider location - this is set to match the
3212 * 'exploding' frame.
3216 public void explodeViews(SplitFrame sf)
3218 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3219 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3220 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3222 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3224 int viewCount = topPanels.size();
3231 * Processing in reverse order works, forwards order leaves the first panels
3232 * not visible. I don't know why!
3234 for (int i = viewCount - 1; i >= 0; i--)
3237 * Make new top and bottom frames. These take over the respective
3238 * AlignmentPanel objects, including their AlignmentViewports, so the
3239 * cdna/protein relationships between the viewports is carried over to the
3242 * explodedGeometry holds the (x, y) position of the previously exploded
3243 * SplitFrame, and the (width, height) of the AlignFrame component
3245 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3246 AlignFrame newTopFrame = new AlignFrame(topPanel);
3247 newTopFrame.setSize(oldTopFrame.getSize());
3248 newTopFrame.setVisible(true);
3249 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3250 .getExplodedGeometry();
3251 if (geometry != null)
3253 newTopFrame.setSize(geometry.getSize());
3256 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3257 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3258 newBottomFrame.setSize(oldBottomFrame.getSize());
3259 newBottomFrame.setVisible(true);
3260 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3261 .getExplodedGeometry();
3262 if (geometry != null)
3264 newBottomFrame.setSize(geometry.getSize());
3267 topPanel.av.setGatherViewsHere(false);
3268 bottomPanel.av.setGatherViewsHere(false);
3269 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3271 if (geometry != null)
3273 splitFrame.setLocation(geometry.getLocation());
3275 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3279 * Clear references to the panels (now relocated in the new SplitFrames)
3280 * before closing the old SplitFrame.
3283 bottomPanels.clear();
3288 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3289 * back into the given SplitFrame as additional views. Note that the gathered
3290 * frames may themselves have multiple views.
3294 public void gatherViews(GSplitFrame source)
3297 * special handling of explodedGeometry for a view within a SplitFrame: - it
3298 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3299 * height) of the AlignFrame component
3301 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3302 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3303 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3304 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3305 myBottomFrame.viewport
3306 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3307 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3308 myTopFrame.viewport.setGatherViewsHere(true);
3309 myBottomFrame.viewport.setGatherViewsHere(true);
3310 String topViewId = myTopFrame.viewport.getSequenceSetId();
3311 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3313 JInternalFrame[] frames = desktop.getAllFrames();
3314 for (JInternalFrame frame : frames)
3316 if (frame instanceof SplitFrame && frame != source)
3318 SplitFrame sf = (SplitFrame) frame;
3319 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3320 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3321 boolean gatherThis = false;
3322 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3324 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3325 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3326 if (topViewId.equals(topPanel.av.getSequenceSetId())
3327 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3330 topPanel.av.setGatherViewsHere(false);
3331 bottomPanel.av.setGatherViewsHere(false);
3332 topPanel.av.setExplodedGeometry(
3333 new Rectangle(sf.getLocation(), topFrame.getSize()));
3334 bottomPanel.av.setExplodedGeometry(
3335 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3336 myTopFrame.addAlignmentPanel(topPanel, false);
3337 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3343 topFrame.getAlignPanels().clear();
3344 bottomFrame.getAlignPanels().clear();
3351 * The dust settles...give focus to the tab we did this from.
3353 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3356 public static groovy.ui.Console getGroovyConsole()
3358 return groovyConsole;
3362 * handles the payload of a drag and drop event.
3364 * TODO refactor to desktop utilities class
3367 * - Data source strings extracted from the drop event
3369 * - protocol for each data source extracted from the drop event
3373 * - the payload from the drop event
3376 public static void transferFromDropTarget(List<String> files,
3377 List<DataSourceType> protocols, DropTargetDropEvent evt,
3378 Transferable t) throws Exception
3381 DataFlavor uriListFlavor = new DataFlavor(
3382 "text/uri-list;class=java.lang.String"), urlFlavour = null;
3385 urlFlavour = new DataFlavor(
3386 "application/x-java-url; class=java.net.URL");
3387 } catch (ClassNotFoundException cfe)
3389 Cache.log.debug("Couldn't instantiate the URL dataflavor.", cfe);
3392 if (urlFlavour != null && t.isDataFlavorSupported(urlFlavour))
3397 java.net.URL url = (URL) t.getTransferData(urlFlavour);
3398 // nb: java 8 osx bug https://bugs.openjdk.java.net/browse/JDK-8156099
3399 // means url may be null.
3402 protocols.add(DataSourceType.URL);
3403 files.add(url.toString());
3404 Cache.log.debug("Drop handled as URL dataflavor "
3405 + files.get(files.size() - 1));
3410 if (Platform.isAMac())
3413 "Please ignore plist error - occurs due to problem with java 8 on OSX");
3417 } catch (Throwable ex)
3419 Cache.log.debug("URL drop handler failed.", ex);
3422 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3424 // Works on Windows and MacOSX
3425 Cache.log.debug("Drop handled as javaFileListFlavor");
3426 for (Object file : (List) t
3427 .getTransferData(DataFlavor.javaFileListFlavor))
3429 files.add(((File) file).toString());
3430 protocols.add(DataSourceType.FILE);
3435 // Unix like behaviour
3436 boolean added = false;
3438 if (t.isDataFlavorSupported(uriListFlavor))
3440 Cache.log.debug("Drop handled as uriListFlavor");
3441 // This is used by Unix drag system
3442 data = (String) t.getTransferData(uriListFlavor);
3446 // fallback to text: workaround - on OSX where there's a JVM bug
3447 Cache.log.debug("standard URIListFlavor failed. Trying text");
3448 // try text fallback
3449 DataFlavor textDf = new DataFlavor(
3450 "text/plain;class=java.lang.String");
3451 if (t.isDataFlavorSupported(textDf))
3453 data = (String) t.getTransferData(textDf);
3456 Cache.log.debug("Plain text drop content returned "
3457 + (data == null ? "Null - failed" : data));
3462 while (protocols.size() < files.size())
3464 Cache.log.debug("Adding missing FILE protocol for "
3465 + files.get(protocols.size()));
3466 protocols.add(DataSourceType.FILE);
3468 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3469 data, "\r\n"); st.hasMoreTokens();)
3472 String s = st.nextToken();
3473 if (s.startsWith("#"))
3475 // the line is a comment (as per the RFC 2483)
3478 java.net.URI uri = new java.net.URI(s);
3479 if (uri.getScheme().toLowerCase().startsWith("http"))
3481 protocols.add(DataSourceType.URL);
3482 files.add(uri.toString());
3486 // otherwise preserve old behaviour: catch all for file objects
3487 java.io.File file = new java.io.File(uri);
3488 protocols.add(DataSourceType.FILE);
3489 files.add(file.toString());
3494 if (Cache.log.isDebugEnabled())
3496 if (data == null || !added)
3499 if (t.getTransferDataFlavors() != null
3500 && t.getTransferDataFlavors().length > 0)
3503 "Couldn't resolve drop data. Here are the supported flavors:");
3504 for (DataFlavor fl : t.getTransferDataFlavors())
3507 "Supported transfer dataflavor: " + fl.toString());
3508 Object df = t.getTransferData(fl);
3511 Cache.log.debug("Retrieves: " + df);
3515 Cache.log.debug("Retrieved nothing");
3521 Cache.log.debug("Couldn't resolve dataflavor for drop: "
3527 if (Platform.isWindows())
3530 Cache.log.debug("Scanning dropped content for Windows Link Files");
3532 // resolve any .lnk files in the file drop
3533 for (int f = 0; f < files.size(); f++)
3535 String source = files.get(f).toLowerCase();
3536 if (protocols.get(f).equals(DataSourceType.FILE)
3537 && (source.endsWith(".lnk") || source.endsWith(".url")
3538 || source.endsWith(".site")))
3541 File lf = new File(files.get(f));
3542 // process link file to get a URL
3543 Cache.log.debug("Found potential link file: " + lf);
3544 WindowsShortcut wscfile = new WindowsShortcut(lf);
3545 String fullname = wscfile.getRealFilename();
3546 protocols.set(f, FormatAdapter.checkProtocol(fullname));
3547 files.set(f, fullname);
3548 Cache.log.debug("Parsed real filename " + fullname
3549 + " to extract protocol: " + protocols.get(f));
3551 catch (Exception ex)
3553 Cache.log.error("Couldn't parse "+files.get(f)+" as a link file.",ex);
3561 * Sets the Preferences property for experimental features to True or False
3562 * depending on the state of the controlling menu item
3565 protected void showExperimental_actionPerformed(boolean selected)
3567 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
3571 * Answers a (possibly empty) list of any structure viewer frames (currently
3572 * for either Jmol or Chimera) which are currently open. This may optionally
3573 * be restricted to viewers of a specified class, or viewers linked to a
3574 * specified alignment panel.
3577 * if not null, only return viewers linked to this panel
3578 * @param structureViewerClass
3579 * if not null, only return viewers of this class
3582 public List<StructureViewerBase> getStructureViewers(
3583 AlignmentPanel apanel,
3584 Class<? extends StructureViewerBase> structureViewerClass)
3586 List<StructureViewerBase> result = new ArrayList<>();
3587 JInternalFrame[] frames = Desktop.instance.getAllFrames();
3589 for (JInternalFrame frame : frames)
3591 if (frame instanceof StructureViewerBase)
3593 if (structureViewerClass == null
3594 || structureViewerClass.isInstance(frame))
3597 || ((StructureViewerBase) frame).isLinkedWith(apanel))
3599 result.add((StructureViewerBase) frame);