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,
392 jconsole = new Console(this, showjconsole);
393 // add essential build information
394 jconsole.setHeader("Jalview Version: "
395 + jalview.bin.Cache.getProperty("VERSION") + "\n"
396 + "Jalview Installation: "
397 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
398 + "\n" + "Build Date: "
399 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
400 + "Java version: " + System.getProperty("java.version") + "\n"
401 + System.getProperty("os.arch") + " "
402 + System.getProperty("os.name") + " "
403 + System.getProperty("os.version"));
405 showConsole(showjconsole);
407 showNews.setVisible(false);
409 experimentalFeatures.setSelected(showExperimental());
411 getIdentifiersOrgData();
415 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
416 // Spawn a thread that shows the splashscreen
418 SwingUtilities.invokeLater(new Runnable()
427 // Thread off a new instance of the file chooser - this reduces the time it
428 // takes to open it later on.
429 new Thread(new Runnable()
434 Cache.log.debug("Filechooser init thread started.");
435 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
436 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
438 Cache.log.debug("Filechooser init thread finished.");
441 // Add the service change listener
442 changeSupport.addJalviewPropertyChangeListener("services",
443 new PropertyChangeListener()
447 public void propertyChange(PropertyChangeEvent evt)
449 Cache.log.debug("Firing service changed event for "
450 + evt.getNewValue());
451 JalviewServicesChanged(evt);
456 } // end BH 2018 ignore
458 this.addWindowListener(new WindowAdapter()
461 public void windowClosing(WindowEvent evt)
468 this.addMouseListener(ma = new MouseAdapter()
471 public void mousePressed(MouseEvent evt)
473 if (evt.isPopupTrigger()) // Mac
475 showPasteMenu(evt.getX(), evt.getY());
480 public void mouseReleased(MouseEvent evt)
482 if (evt.isPopupTrigger()) // Windows
484 showPasteMenu(evt.getX(), evt.getY());
488 desktop.addMouseListener(ma);
493 * Answers true if user preferences to enable experimental features is True
498 public boolean showExperimental()
500 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
501 Boolean.FALSE.toString());
502 return Boolean.valueOf(experimental).booleanValue();
505 public void doConfigureStructurePrefs()
507 // configure services
508 StructureSelectionManager ssm = StructureSelectionManager
509 .getStructureSelectionManager(this);
510 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
512 ssm.setAddTempFacAnnot(jalview.bin.Cache
513 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
514 ssm.setProcessSecondaryStructure(jalview.bin.Cache
515 .getDefault(Preferences.STRUCT_FROM_PDB, true));
516 ssm.setSecStructServices(
517 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
521 ssm.setAddTempFacAnnot(false);
522 ssm.setProcessSecondaryStructure(false);
523 ssm.setSecStructServices(false);
527 public void checkForNews()
536 final Desktop me = this;
537 // Thread off the news reader, in case there are connection problems.
538 addDialogThread(new Runnable()
543 Cache.log.debug("Starting news thread.");
545 jvnews = new BlogReader(me);
546 showNews.setVisible(true);
547 Cache.log.debug("Completed news thread.");
553 public void getIdentifiersOrgData()
555 // Thread off the identifiers fetcher
556 addDialogThread(new Runnable()
561 Cache.log.debug("Downloading data from identifiers.org");
562 UrlDownloadClient client = new UrlDownloadClient();
565 client.download(IdOrgSettings.getUrl(),
566 IdOrgSettings.getDownloadLocation());
567 } catch (IOException e)
569 Cache.log.debug("Exception downloading identifiers.org data"
577 protected void showNews_actionPerformed(ActionEvent e)
579 showNews(showNews.isSelected());
582 void showNews(boolean visible)
591 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
592 showNews.setSelected(visible);
593 if (visible && !jvnews.isVisible())
595 new Thread(new Runnable()
600 long now = System.currentTimeMillis();
601 Desktop.instance.setProgressBar(
602 MessageManager.getString("status.refreshing_news"),
604 jvnews.refreshNews();
605 Desktop.instance.setProgressBar(null, now);
614 * recover the last known dimensions for a jalview window
617 * - empty string is desktop, all other windows have unique prefix
618 * @return null or last known dimensions scaled to current geometry (if last
619 * window geom was known)
621 Rectangle getLastKnownDimensions(String windowName)
623 // TODO: lock aspect ratio for scaling desktop Bug #0058199
624 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
625 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
626 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
627 String width = jalview.bin.Cache
628 .getProperty(windowName + "SCREEN_WIDTH");
629 String height = jalview.bin.Cache
630 .getProperty(windowName + "SCREEN_HEIGHT");
631 if ((x != null) && (y != null) && (width != null) && (height != null))
633 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
634 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
635 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
637 // attempt #1 - try to cope with change in screen geometry - this
638 // version doesn't preserve original jv aspect ratio.
639 // take ratio of current screen size vs original screen size.
640 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
641 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
642 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
643 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
644 // rescale the bounds depending upon the current screen geometry.
645 ix = (int) (ix * sw);
646 iw = (int) (iw * sw);
647 iy = (int) (iy * sh);
648 ih = (int) (ih * sh);
649 while (ix >= screenSize.width)
651 jalview.bin.Cache.log.debug(
652 "Window geometry location recall error: shifting horizontal to within screenbounds.");
653 ix -= screenSize.width;
655 while (iy >= screenSize.height)
657 jalview.bin.Cache.log.debug(
658 "Window geometry location recall error: shifting vertical to within screenbounds.");
659 iy -= screenSize.height;
661 jalview.bin.Cache.log.debug(
662 "Got last known dimensions for " + windowName + ": x:" + ix
663 + " y:" + iy + " width:" + iw + " height:" + ih);
665 // return dimensions for new instance
666 return new Rectangle(ix, iy, iw, ih);
671 private void doVamsasClientCheck()
673 if (/** @j2sNative false && */ // BH 2018
674 jalview.bin.Cache.vamsasJarsPresent())
676 setupVamsasDisconnectedGui();
677 VamsasMenu.setVisible(true);
678 final Desktop us = this;
679 VamsasMenu.addMenuListener(new MenuListener()
681 // this listener remembers when the menu was first selected, and
682 // doesn't rebuild the session list until it has been cleared and
684 boolean refresh = true;
687 public void menuCanceled(MenuEvent e)
693 public void menuDeselected(MenuEvent e)
699 public void menuSelected(MenuEvent e)
703 us.buildVamsasStMenu();
708 vamsasStart.setVisible(true);
712 void showPasteMenu(int x, int y)
714 JPopupMenu popup = new JPopupMenu();
715 JMenuItem item = new JMenuItem(
716 MessageManager.getString("label.paste_new_window"));
717 item.addActionListener(new ActionListener()
720 public void actionPerformed(ActionEvent evt)
727 popup.show(this, x, y);
734 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
735 Transferable contents = c.getContents(this);
737 if (contents != null)
739 String file = (String) contents
740 .getTransferData(DataFlavor.stringFlavor);
742 FileFormatI format = new IdentifyFile().identify(file,
743 DataSourceType.PASTE);
745 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
748 } catch (Exception ex)
751 "Unable to paste alignment from system clipboard:\n" + ex);
756 * Adds and opens the given frame to the desktop
767 public static synchronized void addInternalFrame(
768 final JInternalFrame frame, String title, int w, int h)
770 addInternalFrame(frame, title, true, w, h, true, false);
774 * Add an internal frame to the Jalview desktop
781 * When true, display frame immediately, otherwise, caller must call
782 * setVisible themselves.
788 public static synchronized void addInternalFrame(
789 final JInternalFrame frame, String title, boolean makeVisible,
792 addInternalFrame(frame, title, makeVisible, w, h, true, false);
796 * Add an internal frame to the Jalview desktop and make it visible
809 public static synchronized void addInternalFrame(
810 final JInternalFrame frame, String title, int w, int h,
813 addInternalFrame(frame, title, true, w, h, resizable, false);
817 * Add an internal frame to the Jalview desktop
824 * When true, display frame immediately, otherwise, caller must call
825 * setVisible themselves.
832 * @param ignoreMinSize
833 * Do not set the default minimum size for frame
835 public static synchronized void addInternalFrame(
836 final JInternalFrame frame, String title, boolean makeVisible,
837 int w, int h, boolean resizable, boolean ignoreMinSize)
840 // TODO: allow callers to determine X and Y position of frame (eg. via
842 // TODO: consider fixing method to update entries in the window submenu with
843 // the current window title
845 frame.setTitle(title);
846 if (frame.getWidth() < 1 || frame.getHeight() < 1)
850 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
851 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
852 // IF JALVIEW IS RUNNING HEADLESS
853 // ///////////////////////////////////////////////
854 if (instance == null || (System.getProperty("java.awt.headless") != null
855 && System.getProperty("java.awt.headless").equals("true")))
864 frame.setMinimumSize(
865 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
867 // Set default dimension for Alignment Frame window.
868 // The Alignment Frame window could be added from a number of places,
870 // I did this here in order not to miss out on any Alignment frame.
871 if (frame instanceof AlignFrame)
873 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
874 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
878 frame.setVisible(makeVisible);
879 frame.setClosable(true);
880 frame.setResizable(resizable);
881 frame.setMaximizable(resizable);
882 frame.setIconifiable(resizable);
883 frame.setOpaque(/** @j2sNative true || */
886 if (frame.getX() < 1 && frame.getY() < 1)
888 frame.setLocation(xOffset * openFrameCount,
889 yOffset * ((openFrameCount - 1) % 10) + yOffset);
893 * add an entry for the new frame in the Window menu
894 * (and remove it when the frame is closed)
896 final JMenuItem menuItem = new JMenuItem(title);
897 frame.addInternalFrameListener(new InternalFrameAdapter()
900 public void internalFrameActivated(InternalFrameEvent evt)
902 JInternalFrame itf = desktop.getSelectedFrame();
905 if (itf instanceof AlignFrame)
907 Jalview.setCurrentAlignFrame((AlignFrame) itf);
914 public void internalFrameClosed(InternalFrameEvent evt)
916 PaintRefresher.RemoveComponent(frame);
919 * defensive check to prevent frames being
920 * added half off the window
922 if (openFrameCount > 0)
928 * ensure no reference to alignFrame retained by menu item listener
930 if (menuItem.getActionListeners().length > 0)
932 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
934 windowMenu.remove(menuItem);
938 menuItem.addActionListener(new ActionListener()
941 public void actionPerformed(ActionEvent e)
945 frame.setSelected(true);
946 frame.setIcon(false);
947 } catch (java.beans.PropertyVetoException ex)
954 setKeyBindings(frame);
958 windowMenu.add(menuItem);
963 frame.setSelected(true);
964 frame.requestFocus();
965 } catch (java.beans.PropertyVetoException ve)
967 } catch (java.lang.ClassCastException cex)
970 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
976 * Add key bindings to a JInternalFrame so that Ctrl-W and Cmd-W will close
981 private static void setKeyBindings(JInternalFrame frame)
983 @SuppressWarnings("serial")
984 final Action closeAction = new AbstractAction()
987 public void actionPerformed(ActionEvent e)
994 * set up key bindings for Ctrl-W and Cmd-W, with the same (Close) action
996 KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
997 InputEvent.CTRL_DOWN_MASK);
998 KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
999 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
1001 InputMap inputMap = frame
1002 .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
1003 String ctrlW = ctrlWKey.toString();
1004 inputMap.put(ctrlWKey, ctrlW);
1005 inputMap.put(cmdWKey, ctrlW);
1007 ActionMap actionMap = frame.getActionMap();
1008 actionMap.put(ctrlW, closeAction);
1012 public void lostOwnership(Clipboard clipboard, Transferable contents)
1016 Desktop.jalviewClipboard = null;
1019 internalCopy = false;
1023 public void dragEnter(DropTargetDragEvent evt)
1028 public void dragExit(DropTargetEvent evt)
1033 public void dragOver(DropTargetDragEvent evt)
1038 public void dropActionChanged(DropTargetDragEvent evt)
1049 public void drop(DropTargetDropEvent evt)
1051 boolean success = true;
1052 // JAL-1552 - acceptDrop required before getTransferable call for
1053 // Java's Transferable for native dnd
1054 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1055 Transferable t = evt.getTransferable();
1056 List<String> files = new ArrayList<>();
1057 List<DataSourceType> protocols = new ArrayList<>();
1061 Desktop.transferFromDropTarget(files, protocols, evt, t);
1062 } catch (Exception e)
1064 e.printStackTrace();
1072 for (int i = 0; i < files.size(); i++)
1074 String file = files.get(i).toString();
1075 DataSourceType protocol = (protocols == null)
1076 ? DataSourceType.FILE
1078 FileFormatI format = null;
1080 if (file.endsWith(".jar"))
1082 format = FileFormat.Jalview;
1087 format = new IdentifyFile().identify(file, protocol);
1090 new FileLoader().LoadFile(file, protocol, format);
1093 } catch (Exception ex)
1098 evt.dropComplete(success); // need this to ensure input focus is properly
1099 // transfered to any new windows created
1109 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1111 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1112 JalviewFileChooser chooser = JalviewFileChooser
1113 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1115 chooser.setFileView(new JalviewFileView());
1116 chooser.setDialogTitle(
1117 MessageManager.getString("label.open_local_file"));
1118 chooser.setToolTipText(MessageManager.getString("action.open"));
1120 int value = chooser.showOpenDialog(this);
1122 if (value == JalviewFileChooser.APPROVE_OPTION)
1124 String choice = chooser.getSelectedFile().getPath();
1125 Cache.setProperty("LAST_DIRECTORY",
1126 chooser.getSelectedFile().getParent());
1128 FileFormatI format = chooser.getSelectedFormat();
1131 * Call IdentifyFile to verify the file contains what its extension implies.
1132 * Skip this step for dynamically added file formats, because
1133 * IdentifyFile does not know how to recognise them.
1135 if (FileFormats.getInstance().isIdentifiable(format))
1139 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1140 } catch (FileFormatException e)
1142 // format = null; //??
1146 if (viewport != null)
1148 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1153 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1165 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1167 // This construct allows us to have a wider textfield
1169 JLabel label = new JLabel(
1170 MessageManager.getString("label.input_file_url"));
1172 JComboBox history = new JComboBox();
1173 JPanel panel = new JPanel(new GridLayout(2, 1));
1176 history.setPreferredSize(new Dimension(400, 20));
1177 history.setEditable(true);
1178 history.addItem("http://www.");
1180 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1184 if (historyItems != null)
1186 st = new StringTokenizer(historyItems, "\t");
1188 while (st.hasMoreTokens())
1190 history.addItem(st.nextElement());
1194 // BH 2018 -- providing a callback for SwingJS
1195 String dialogOption = "label.input_alignment_from_url";
1196 desktop.dialogData = new Object[] { dialogOption, viewport, history };
1197 desktop.onDialogReturn(
1198 JvOptionPane.showInternalConfirmDialog(desktop, panel,
1199 MessageManager.getString(dialogOption),
1200 JvOptionPane.OK_CANCEL_OPTION));
1202 // no code may follow this, as SwingJS will not block
1203 // callback in JavaScript comes via a property change event
1209 * Opens the CutAndPaste window for the user to paste an alignment in to
1212 * - if not null, the pasted alignment is added to the current
1213 * alignment; if null, to a new alignment window
1216 public void inputTextboxMenuItem_actionPerformed(
1217 AlignmentViewPanel viewPanel)
1219 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1220 cap.setForInput(viewPanel);
1221 Desktop.addInternalFrame(cap,
1222 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1232 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1233 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1235 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1236 screen.height + "");
1237 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1238 getWidth(), getHeight()));
1240 if (jconsole != null)
1242 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1243 jconsole.stopConsole();
1247 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1250 if (dialogExecutor != null)
1252 dialogExecutor.shutdownNow();
1254 closeAll_actionPerformed(null);
1256 if (groovyConsole != null)
1258 // suppress a possible repeat prompt to save script
1259 groovyConsole.setDirty(false);
1260 groovyConsole.exit();
1265 private void storeLastKnownDimensions(String string, Rectangle jc)
1267 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1268 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1269 + " height:" + jc.height);
1271 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1272 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1273 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1274 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1284 public void aboutMenuItem_actionPerformed(ActionEvent e)
1286 // StringBuffer message = getAboutMessage(false);
1287 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1289 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1290 new Thread(new Runnable()
1295 new SplashScreen(true);
1300 public StringBuffer getAboutMessage(boolean shortv)
1302 StringBuffer message = new StringBuffer();
1303 message.append("<html>");
1306 message.append("<h1><strong>Version: "
1307 + jalview.bin.Cache.getProperty("VERSION")
1308 + "</strong></h1>");
1309 message.append("<strong>Last Updated: <em>"
1310 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1311 + "</em></strong>");
1317 message.append("<strong>Version "
1318 + jalview.bin.Cache.getProperty("VERSION")
1319 + "; last updated: "
1320 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1323 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1324 .equals("Checking"))
1326 message.append("<br>...Checking latest version...</br>");
1328 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1329 .equals(jalview.bin.Cache.getProperty("VERSION")))
1331 boolean red = false;
1332 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1333 .indexOf("automated build") == -1)
1336 // Displayed when code version and jnlp version do not match and code
1337 // version is not a development build
1338 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1341 message.append("<br>!! Version "
1342 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1344 + " is available for download from "
1345 + jalview.bin.Cache.getDefault("www.jalview.org",
1346 "http://www.jalview.org")
1350 message.append("</div>");
1353 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1355 "The Jalview Authors (See AUTHORS file for current list)")
1356 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1357 + "<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"
1358 + "<br><br>If you use Jalview, please cite:"
1359 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1360 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1361 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1373 public void documentationMenuItem_actionPerformed(ActionEvent e)
1377 Help.showHelpWindow();
1378 } catch (Exception ex)
1384 public void closeAll_actionPerformed(ActionEvent e)
1386 // TODO show a progress bar while closing?
1387 JInternalFrame[] frames = desktop.getAllFrames();
1388 for (int i = 0; i < frames.length; i++)
1392 frames[i].setClosed(true);
1393 } catch (java.beans.PropertyVetoException ex)
1397 Jalview.setCurrentAlignFrame(null);
1398 System.out.println("ALL CLOSED");
1399 if (v_client != null)
1401 // TODO clear binding to vamsas document objects on close_all
1405 * reset state of singleton objects as appropriate (clear down session state
1406 * when all windows are closed)
1408 StructureSelectionManager ssm = StructureSelectionManager
1409 .getStructureSelectionManager(this);
1417 public void raiseRelated_actionPerformed(ActionEvent e)
1419 reorderAssociatedWindows(false, false);
1423 public void minimizeAssociated_actionPerformed(ActionEvent e)
1425 reorderAssociatedWindows(true, false);
1428 void closeAssociatedWindows()
1430 reorderAssociatedWindows(false, true);
1436 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1440 protected void garbageCollect_actionPerformed(ActionEvent e)
1442 // We simply collect the garbage
1443 jalview.bin.Cache.log.debug("Collecting garbage...");
1445 jalview.bin.Cache.log.debug("Finished garbage collection.");
1452 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1456 protected void showMemusage_actionPerformed(ActionEvent e)
1458 desktop.showMemoryUsage(showMemusage.isSelected());
1465 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1469 protected void showConsole_actionPerformed(ActionEvent e)
1471 showConsole(showConsole.isSelected());
1474 Console jconsole = null;
1477 * control whether the java console is visible or not
1481 void showConsole(boolean selected)
1483 // TODO: decide if we should update properties file
1484 if (jconsole != null) // BH 2018
1486 showConsole.setSelected(selected);
1487 Cache.setProperty("SHOW_JAVA_CONSOLE",
1488 Boolean.valueOf(selected).toString());
1489 jconsole.setVisible(selected);
1493 void reorderAssociatedWindows(boolean minimize, boolean close)
1495 JInternalFrame[] frames = desktop.getAllFrames();
1496 if (frames == null || frames.length < 1)
1501 AlignmentViewport source = null, target = null;
1502 if (frames[0] instanceof AlignFrame)
1504 source = ((AlignFrame) frames[0]).getCurrentView();
1506 else if (frames[0] instanceof TreePanel)
1508 source = ((TreePanel) frames[0]).getViewPort();
1510 else if (frames[0] instanceof PCAPanel)
1512 source = ((PCAPanel) frames[0]).av;
1514 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1516 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1521 for (int i = 0; i < frames.length; i++)
1524 if (frames[i] == null)
1528 if (frames[i] instanceof AlignFrame)
1530 target = ((AlignFrame) frames[i]).getCurrentView();
1532 else if (frames[i] instanceof TreePanel)
1534 target = ((TreePanel) frames[i]).getViewPort();
1536 else if (frames[i] instanceof PCAPanel)
1538 target = ((PCAPanel) frames[i]).av;
1540 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1542 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1545 if (source == target)
1551 frames[i].setClosed(true);
1555 frames[i].setIcon(minimize);
1558 frames[i].toFront();
1562 } catch (java.beans.PropertyVetoException ex)
1577 protected void preferences_actionPerformed(ActionEvent e)
1589 public void saveState_actionPerformed(ActionEvent e)
1591 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1594 chooser.setFileView(new JalviewFileView());
1595 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1597 int value = chooser.showSaveDialog(this);
1599 if (value == JalviewFileChooser.APPROVE_OPTION)
1601 final Desktop me = this;
1602 final java.io.File choice = chooser.getSelectedFile();
1603 setProjectFile(choice);
1605 new Thread(new Runnable()
1610 // TODO: refactor to Jalview desktop session controller action.
1611 setProgressBar(MessageManager.formatMessage(
1612 "label.saving_jalview_project", new Object[]
1613 { choice.getName() }), choice.hashCode());
1614 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1615 choice.getParent());
1616 // TODO catch and handle errors for savestate
1617 // TODO prevent user from messing with the Desktop whilst we're saving
1620 new Jalview2XML().saveState(choice);
1621 } catch (OutOfMemoryError oom)
1624 "Whilst saving current state to " + choice.getName(),
1626 } catch (Exception ex)
1629 "Problems whilst trying to save to " + choice.getName(),
1631 JvOptionPane.showMessageDialog(me,
1632 MessageManager.formatMessage(
1633 "label.error_whilst_saving_current_state_to",
1635 { choice.getName() }),
1636 MessageManager.getString("label.couldnt_save_project"),
1637 JvOptionPane.WARNING_MESSAGE);
1639 setProgressBar(null, choice.hashCode());
1645 private void setProjectFile(File choice)
1647 this.projectFile = choice;
1650 public File getProjectFile()
1652 return this.projectFile;
1662 public void loadState_actionPerformed(ActionEvent e)
1664 JalviewFileChooser chooser = new JalviewFileChooser(
1665 Cache.getProperty("LAST_DIRECTORY"), new String[]
1668 { "Jalview Project", "Jalview Project (old)" },
1670 chooser.setFileView(new JalviewFileView());
1671 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1673 int value = chooser.showOpenDialog(this);
1675 if (value == JalviewFileChooser.APPROVE_OPTION)
1677 final File selectedFile = chooser.getSelectedFile();
1678 setProjectFile(selectedFile);
1679 final String choice = selectedFile.getAbsolutePath();
1680 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1681 new Thread(new Runnable()
1686 setProgressBar(MessageManager.formatMessage(
1687 "label.loading_jalview_project", new Object[]
1688 { choice }), choice.hashCode());
1691 new Jalview2XML().loadJalviewAlign(choice);
1692 } catch (OutOfMemoryError oom)
1694 new OOMWarning("Whilst loading project from " + choice, oom);
1695 } catch (Exception ex)
1698 "Problems whilst loading project from " + choice, ex);
1699 JvOptionPane.showMessageDialog(Desktop.desktop,
1700 MessageManager.formatMessage(
1701 "label.error_whilst_loading_project_from",
1704 MessageManager.getString("label.couldnt_load_project"),
1705 JvOptionPane.WARNING_MESSAGE);
1707 setProgressBar(null, choice.hashCode());
1714 public void inputSequence_actionPerformed(ActionEvent e)
1716 new SequenceFetcher(this);
1719 JPanel progressPanel;
1721 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1723 public void startLoading(final String fileName)
1725 if (fileLoadingCount == 0)
1727 fileLoadingPanels.add(addProgressPanel(MessageManager
1728 .formatMessage("label.loading_file", new Object[]
1734 private JPanel addProgressPanel(String string)
1736 if (progressPanel == null)
1738 progressPanel = new JPanel(new GridLayout(1, 1));
1739 totalProgressCount = 0;
1740 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1742 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1743 JProgressBar progressBar = new JProgressBar();
1744 progressBar.setIndeterminate(true);
1746 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1748 thisprogress.add(progressBar, BorderLayout.CENTER);
1749 progressPanel.add(thisprogress);
1750 ((GridLayout) progressPanel.getLayout()).setRows(
1751 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1752 ++totalProgressCount;
1753 instance.validate();
1754 return thisprogress;
1757 int totalProgressCount = 0;
1759 private void removeProgressPanel(JPanel progbar)
1761 if (progressPanel != null)
1763 synchronized (progressPanel)
1765 progressPanel.remove(progbar);
1766 GridLayout gl = (GridLayout) progressPanel.getLayout();
1767 gl.setRows(gl.getRows() - 1);
1768 if (--totalProgressCount < 1)
1770 this.getContentPane().remove(progressPanel);
1771 progressPanel = null;
1778 public void stopLoading()
1781 if (fileLoadingCount < 1)
1783 while (fileLoadingPanels.size() > 0)
1785 removeProgressPanel(fileLoadingPanels.remove(0));
1787 fileLoadingPanels.clear();
1788 fileLoadingCount = 0;
1793 public static int getViewCount(String alignmentId)
1795 AlignmentViewport[] aps = getViewports(alignmentId);
1796 return (aps == null) ? 0 : aps.length;
1801 * @param alignmentId
1802 * - if null, all sets are returned
1803 * @return all AlignmentPanels concerning the alignmentId sequence set
1805 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1807 if (Desktop.desktop == null)
1809 // no frames created and in headless mode
1810 // TODO: verify that frames are recoverable when in headless mode
1813 List<AlignmentPanel> aps = new ArrayList<>();
1814 AlignFrame[] frames = getAlignFrames();
1819 for (AlignFrame af : frames)
1821 for (AlignmentPanel ap : af.alignPanels)
1823 if (alignmentId == null
1824 || alignmentId.equals(ap.av.getSequenceSetId()))
1830 if (aps.size() == 0)
1834 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1839 * get all the viewports on an alignment.
1841 * @param sequenceSetId
1842 * unique alignment id (may be null - all viewports returned in that
1844 * @return all viewports on the alignment bound to sequenceSetId
1846 public static AlignmentViewport[] getViewports(String sequenceSetId)
1848 List<AlignmentViewport> viewp = new ArrayList<>();
1849 if (desktop != null)
1851 AlignFrame[] frames = Desktop.getAlignFrames();
1853 for (AlignFrame afr : frames)
1855 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1856 .equals(sequenceSetId))
1858 if (afr.alignPanels != null)
1860 for (AlignmentPanel ap : afr.alignPanels)
1862 if (sequenceSetId == null
1863 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1871 viewp.add(afr.getViewport());
1875 if (viewp.size() > 0)
1877 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1884 * Explode the views in the given frame into separate AlignFrame
1888 public static void explodeViews(AlignFrame af)
1890 int size = af.alignPanels.size();
1896 for (int i = 0; i < size; i++)
1898 AlignmentPanel ap = af.alignPanels.get(i);
1899 AlignFrame newaf = new AlignFrame(ap);
1902 * Restore the view's last exploded frame geometry if known. Multiple
1903 * views from one exploded frame share and restore the same (frame)
1904 * position and size.
1906 Rectangle geometry = ap.av.getExplodedGeometry();
1907 if (geometry != null)
1909 newaf.setBounds(geometry);
1912 ap.av.setGatherViewsHere(false);
1914 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1915 AlignFrame.DEFAULT_HEIGHT);
1918 af.alignPanels.clear();
1919 af.closeMenuItem_actionPerformed(true);
1924 * Gather expanded views (separate AlignFrame's) with the same sequence set
1925 * identifier back in to this frame as additional views, and close the
1926 * expanded views. Note the expanded frames may themselves have multiple
1927 * views. We take the lot.
1931 public void gatherViews(AlignFrame source)
1933 source.viewport.setGatherViewsHere(true);
1934 source.viewport.setExplodedGeometry(source.getBounds());
1935 JInternalFrame[] frames = desktop.getAllFrames();
1936 String viewId = source.viewport.getSequenceSetId();
1938 for (int t = 0; t < frames.length; t++)
1940 if (frames[t] instanceof AlignFrame && frames[t] != source)
1942 AlignFrame af = (AlignFrame) frames[t];
1943 boolean gatherThis = false;
1944 for (int a = 0; a < af.alignPanels.size(); a++)
1946 AlignmentPanel ap = af.alignPanels.get(a);
1947 if (viewId.equals(ap.av.getSequenceSetId()))
1950 ap.av.setGatherViewsHere(false);
1951 ap.av.setExplodedGeometry(af.getBounds());
1952 source.addAlignmentPanel(ap, false);
1958 af.alignPanels.clear();
1959 af.closeMenuItem_actionPerformed(true);
1966 jalview.gui.VamsasApplication v_client = null;
1969 public void vamsasImport_actionPerformed(ActionEvent e)
1971 if (v_client == null)
1973 // Load and try to start a session.
1974 JalviewFileChooser chooser = new JalviewFileChooser(
1975 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1977 chooser.setFileView(new JalviewFileView());
1978 chooser.setDialogTitle(
1979 MessageManager.getString("label.open_saved_vamsas_session"));
1980 chooser.setToolTipText(MessageManager.getString(
1981 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1983 int value = chooser.showOpenDialog(this);
1985 if (value == JalviewFileChooser.APPROVE_OPTION)
1987 String fle = chooser.getSelectedFile().toString();
1988 if (!vamsasImport(chooser.getSelectedFile()))
1990 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1991 MessageManager.formatMessage(
1992 "label.couldnt_import_as_vamsas_session",
1996 .getString("label.vamsas_document_import_failed"),
1997 JvOptionPane.ERROR_MESSAGE);
2003 jalview.bin.Cache.log.error(
2004 "Implementation error - load session from a running session is not supported.");
2009 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2012 * @return true if import was a success and a session was started.
2014 public boolean vamsasImport(URL url)
2016 // TODO: create progress bar
2017 if (v_client != null)
2020 jalview.bin.Cache.log.error(
2021 "Implementation error - load session from a running session is not supported.");
2027 // copy the URL content to a temporary local file
2028 // TODO: be a bit cleverer here with nio (?!)
2029 File file = File.createTempFile("vdocfromurl", ".vdj");
2030 FileOutputStream fos = new FileOutputStream(file);
2031 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2032 byte[] buffer = new byte[2048];
2034 while ((ln = bis.read(buffer)) > -1)
2036 fos.write(buffer, 0, ln);
2040 v_client = new jalview.gui.VamsasApplication(this, file,
2041 url.toExternalForm());
2042 } catch (Exception ex)
2044 jalview.bin.Cache.log.error(
2045 "Failed to create new vamsas session from contents of URL "
2050 setupVamsasConnectedGui();
2051 v_client.initial_update(); // TODO: thread ?
2052 return v_client.inSession();
2056 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2059 * @return true if import was a success and a session was started.
2061 public boolean vamsasImport(File file)
2063 if (v_client != null)
2066 jalview.bin.Cache.log.error(
2067 "Implementation error - load session from a running session is not supported.");
2071 setProgressBar(MessageManager.formatMessage(
2072 "status.importing_vamsas_session_from", new Object[]
2073 { file.getName() }), file.hashCode());
2076 v_client = new jalview.gui.VamsasApplication(this, file, null);
2077 } catch (Exception ex)
2079 setProgressBar(MessageManager.formatMessage(
2080 "status.importing_vamsas_session_from", new Object[]
2081 { file.getName() }), file.hashCode());
2082 jalview.bin.Cache.log.error(
2083 "New vamsas session from existing session file failed:", ex);
2086 setupVamsasConnectedGui();
2087 v_client.initial_update(); // TODO: thread ?
2088 setProgressBar(MessageManager.formatMessage(
2089 "status.importing_vamsas_session_from", new Object[]
2090 { file.getName() }), file.hashCode());
2091 return v_client.inSession();
2094 public boolean joinVamsasSession(String mysesid)
2096 if (v_client != null)
2098 throw new Error(MessageManager
2099 .getString("error.try_join_vamsas_session_another"));
2101 if (mysesid == null)
2104 MessageManager.getString("error.invalid_vamsas_session_id"));
2106 v_client = new VamsasApplication(this, mysesid);
2107 setupVamsasConnectedGui();
2108 v_client.initial_update();
2109 return (v_client.inSession());
2113 public void vamsasStart_actionPerformed(ActionEvent e)
2115 if (v_client == null)
2118 // we just start a default session for moment.
2120 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2121 * getProperty("LAST_DIRECTORY"));
2123 * chooser.setFileView(new JalviewFileView());
2124 * chooser.setDialogTitle("Load Vamsas file");
2125 * chooser.setToolTipText("Import");
2127 * int value = chooser.showOpenDialog(this);
2129 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2130 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2132 v_client = new VamsasApplication(this);
2133 setupVamsasConnectedGui();
2134 v_client.initial_update(); // TODO: thread ?
2138 // store current data in session.
2139 v_client.push_update(); // TODO: thread
2143 protected void setupVamsasConnectedGui()
2145 vamsasStart.setText(MessageManager.getString("label.session_update"));
2146 vamsasSave.setVisible(true);
2147 vamsasStop.setVisible(true);
2148 vamsasImport.setVisible(false); // Document import to existing session is
2149 // not possible for vamsas-client-1.0.
2152 protected void setupVamsasDisconnectedGui()
2154 vamsasSave.setVisible(false);
2155 vamsasStop.setVisible(false);
2156 vamsasImport.setVisible(true);
2158 .setText(MessageManager.getString("label.new_vamsas_session"));
2162 public void vamsasStop_actionPerformed(ActionEvent e)
2164 if (v_client != null)
2166 v_client.end_session();
2168 setupVamsasDisconnectedGui();
2172 protected void buildVamsasStMenu()
2174 if (v_client == null)
2176 String[] sess = null;
2179 sess = VamsasApplication.getSessionList();
2180 } catch (Exception e)
2182 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2188 jalview.bin.Cache.log.debug(
2189 "Got current sessions list: " + sess.length + " entries.");
2190 VamsasStMenu.removeAll();
2191 for (int i = 0; i < sess.length; i++)
2193 JMenuItem sessit = new JMenuItem();
2194 sessit.setText(sess[i]);
2195 sessit.setToolTipText(MessageManager
2196 .formatMessage("label.connect_to_session", new Object[]
2198 final Desktop dsktp = this;
2199 final String mysesid = sess[i];
2200 sessit.addActionListener(new ActionListener()
2204 public void actionPerformed(ActionEvent e)
2206 if (dsktp.v_client == null)
2208 Thread rthr = new Thread(new Runnable()
2214 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2215 dsktp.setupVamsasConnectedGui();
2216 dsktp.v_client.initial_update();
2224 VamsasStMenu.add(sessit);
2226 // don't show an empty menu.
2227 VamsasStMenu.setVisible(sess.length > 0);
2232 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2233 VamsasStMenu.removeAll();
2234 VamsasStMenu.setVisible(false);
2239 // Not interested in the content. Just hide ourselves.
2240 VamsasStMenu.setVisible(false);
2245 public void vamsasSave_actionPerformed(ActionEvent e)
2247 if (v_client != null)
2249 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2250 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2253 chooser.setFileView(new JalviewFileView());
2254 chooser.setDialogTitle(MessageManager
2255 .getString("label.save_vamsas_document_archive"));
2257 int value = chooser.showSaveDialog(this);
2259 if (value == JalviewFileChooser.APPROVE_OPTION)
2261 java.io.File choice = chooser.getSelectedFile();
2262 JPanel progpanel = addProgressPanel(MessageManager
2263 .formatMessage("label.saving_vamsas_doc", new Object[]
2264 { choice.getName() }));
2265 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2266 String warnmsg = null;
2267 String warnttl = null;
2270 v_client.vclient.storeDocument(choice);
2273 warnttl = "Serious Problem saving Vamsas Document";
2274 warnmsg = ex.toString();
2275 jalview.bin.Cache.log
2276 .error("Error Whilst saving document to " + choice, ex);
2278 } catch (Exception ex)
2280 warnttl = "Problem saving Vamsas Document.";
2281 warnmsg = ex.toString();
2282 jalview.bin.Cache.log.warn(
2283 "Exception Whilst saving document to " + choice, ex);
2286 removeProgressPanel(progpanel);
2287 if (warnmsg != null)
2289 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2291 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2297 JPanel vamUpdate = null;
2300 * hide vamsas user gui bits when a vamsas document event is being handled.
2303 * true to hide gui, false to reveal gui
2305 public void setVamsasUpdate(boolean b)
2307 Cache.log.debug("Setting gui for Vamsas update "
2308 + (b ? "in progress" : "finished"));
2310 if (vamUpdate != null)
2312 this.removeProgressPanel(vamUpdate);
2316 vamUpdate = this.addProgressPanel(
2317 MessageManager.getString("label.updating_vamsas_session"));
2319 vamsasStart.setVisible(!b);
2320 vamsasStop.setVisible(!b);
2321 vamsasSave.setVisible(!b);
2324 public JInternalFrame[] getAllFrames()
2326 return desktop.getAllFrames();
2330 * Checks the given url to see if it gives a response indicating that the user
2331 * should be informed of a new questionnaire.
2335 public void checkForQuestionnaire(String url)
2337 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2338 // javax.swing.SwingUtilities.invokeLater(jvq);
2339 new Thread(jvq).start();
2342 public void checkURLLinks()
2344 // Thread off the URL link checker
2345 addDialogThread(new Runnable()
2350 if (/** @j2sNative false && */ // BH 2018
2351 Cache.getDefault("CHECKURLLINKS", true))
2353 // check what the actual links are - if it's just the default don't
2354 // bother with the warning
2355 List<String> links = Preferences.sequenceUrlLinks
2358 // only need to check links if there is one with a
2359 // SEQUENCE_ID which is not the default EMBL_EBI link
2360 ListIterator<String> li = links.listIterator();
2361 boolean check = false;
2362 List<JLabel> urls = new ArrayList<>();
2363 while (li.hasNext())
2365 String link = li.next();
2366 if (link.contains(SEQUENCE_ID)
2367 && !UrlConstants.isDefaultString(link))
2370 int barPos = link.indexOf("|");
2371 String urlMsg = barPos == -1 ? link
2372 : link.substring(0, barPos) + ": "
2373 + link.substring(barPos + 1);
2374 urls.add(new JLabel(urlMsg));
2382 // ask user to check in case URL links use old style tokens
2383 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2384 JPanel msgPanel = new JPanel();
2385 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2386 msgPanel.add(Box.createVerticalGlue());
2387 JLabel msg = new JLabel(MessageManager
2388 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2389 JLabel msg2 = new JLabel(MessageManager
2390 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2392 for (JLabel url : urls)
2398 final JCheckBox jcb = new JCheckBox(
2399 MessageManager.getString("label.do_not_display_again"));
2400 jcb.addActionListener(new ActionListener()
2403 public void actionPerformed(ActionEvent e)
2405 // update Cache settings for "don't show this again"
2406 boolean showWarningAgain = !jcb.isSelected();
2407 Cache.setProperty("CHECKURLLINKS",
2408 Boolean.valueOf(showWarningAgain).toString());
2413 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2415 .getString("label.SEQUENCE_ID_no_longer_used"),
2416 JvOptionPane.WARNING_MESSAGE);
2423 * Proxy class for JDesktopPane which optionally displays the current memory
2424 * usage and highlights the desktop area with a red bar if free memory runs
2429 public class MyDesktopPane extends JDesktopPane
2430 implements Runnable, PropertyChangeListener
2433 public Object[] dialogData;
2437 public void propertyChange(PropertyChangeEvent event)
2439 Object val = event.getNewValue();
2440 String name = event.getPropertyName();
2441 System.out.println(name);
2442 switch (event.getSource().getClass().getName())
2444 case "javax.swing.JOptionPane":
2448 onDialogReturn(val);
2451 if (val instanceof Integer)
2453 onDialogReturn(((Integer) val).intValue());
2457 onDialogReturn(val);
2462 case "javax.swing.ColorChooserDialog":
2465 case "SelectedColor":
2466 onDialogReturn(val);
2470 case "javax.swing.JFileChooser":
2473 case "SelectedFile":
2474 File file = (File) val;
2475 byte[] array = (val == null ? null
2476 : /** @j2sNative file._bytes || */
2478 onDialogReturn("fileName is '" + file.getName() + "'\n\n"
2479 + new String(array));
2484 System.out.println(event.getSource().getClass().getName() + " "
2485 + event.getPropertyName() + ": " + event.getNewValue());
2488 // JSCOmponent.DialogCaller interface
2489 private void onDialogReturn(Object value)
2491 System.out.println("not implemented");
2494 // JSCOmponent.DialogCaller interface
2495 void onDialogReturn(int value)
2497 if (value != Math.floor(value))
2499 // in JavaScript, this will be NaN, oddly enough
2503 switch ((String) dialogData[0])
2505 case "label.input_alignment_from_url":
2506 // reconstruct the parameter data
2508 AlignViewport viewport = (AlignViewport) dialogData[1];
2509 JComboBox history = (JComboBox) dialogData[2];
2510 // the rest of this is unchangaed
2511 if (reply != JvOptionPane.OK_OPTION)
2516 String url = history.getSelectedItem().toString();
2518 if (url.toLowerCase().endsWith(".jar"))
2520 if (viewport != null)
2522 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
2523 FileFormat.Jalview);
2527 new FileLoader().LoadFile(url, DataSourceType.URL,
2528 FileFormat.Jalview);
2533 FileFormatI format = null;
2536 format = new IdentifyFile().identify(url, DataSourceType.URL);
2537 } catch (FileFormatException e)
2539 // TODO revise error handling, distinguish between
2540 // URL not found and response not valid
2545 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2546 MessageManager.formatMessage("label.couldnt_locate",
2549 MessageManager.getString("label.url_not_found"),
2550 JvOptionPane.WARNING_MESSAGE);
2555 if (viewport != null)
2557 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
2562 new FileLoader().LoadFile(url, DataSourceType.URL, format);
2571 private static final float ONE_MB = 1048576f;
2573 boolean showMemoryUsage = false;
2577 java.text.NumberFormat df;
2579 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2582 public MyDesktopPane(boolean showMemoryUsage)
2584 showMemoryUsage(showMemoryUsage);
2587 public void showMemoryUsage(boolean showMemory)
2589 this.showMemoryUsage = showMemory;
2592 Thread worker = new Thread(this);
2598 public boolean isShowMemoryUsage()
2600 return showMemoryUsage;
2606 df = java.text.NumberFormat.getNumberInstance();
2607 df.setMaximumFractionDigits(2);
2608 runtime = Runtime.getRuntime();
2610 while (showMemoryUsage)
2614 maxMemory = runtime.maxMemory() / ONE_MB;
2615 allocatedMemory = runtime.totalMemory() / ONE_MB;
2616 freeMemory = runtime.freeMemory() / ONE_MB;
2617 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2619 percentUsage = (totalFreeMemory / maxMemory) * 100;
2621 // if (percentUsage < 20)
2623 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2625 // instance.set.setBorder(border1);
2628 // sleep after showing usage
2630 } catch (Exception ex)
2632 ex.printStackTrace();
2638 public void paintComponent(Graphics g)
2640 if (showMemoryUsage && g != null && df != null)
2642 if (percentUsage < 20)
2644 g.setColor(Color.red);
2646 FontMetrics fm = g.getFontMetrics();
2649 g.drawString(MessageManager.formatMessage("label.memory_stats",
2651 { df.format(totalFreeMemory), df.format(maxMemory),
2652 df.format(percentUsage) }),
2653 10, getHeight() - fm.getHeight());
2661 * Accessor method to quickly get all the AlignmentFrames loaded.
2663 * @return an array of AlignFrame, or null if none found
2665 public static AlignFrame[] getAlignFrames()
2667 if (Jalview.isHeadlessMode())
2669 // Desktop.desktop is null in headless mode
2670 return new AlignFrame[] { Jalview.currentAlignFrame };
2673 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2679 List<AlignFrame> avp = new ArrayList<>();
2681 for (int i = frames.length - 1; i > -1; i--)
2683 if (frames[i] instanceof AlignFrame)
2685 avp.add((AlignFrame) frames[i]);
2687 else if (frames[i] instanceof SplitFrame)
2690 * Also check for a split frame containing an AlignFrame
2692 GSplitFrame sf = (GSplitFrame) frames[i];
2693 if (sf.getTopFrame() instanceof AlignFrame)
2695 avp.add((AlignFrame) sf.getTopFrame());
2697 if (sf.getBottomFrame() instanceof AlignFrame)
2699 avp.add((AlignFrame) sf.getBottomFrame());
2703 if (avp.size() == 0)
2707 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2712 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2716 public GStructureViewer[] getJmols()
2718 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2724 List<GStructureViewer> avp = new ArrayList<>();
2726 for (int i = frames.length - 1; i > -1; i--)
2728 if (frames[i] instanceof AppJmol)
2730 GStructureViewer af = (GStructureViewer) frames[i];
2734 if (avp.size() == 0)
2738 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2743 * Add Groovy Support to Jalview
2746 public void groovyShell_actionPerformed()
2750 openGroovyConsole();
2751 } catch (Exception ex)
2753 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2754 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2756 MessageManager.getString("label.couldnt_create_groovy_shell"),
2757 MessageManager.getString("label.groovy_support_failed"),
2758 JvOptionPane.ERROR_MESSAGE);
2763 * Open the Groovy console
2765 void openGroovyConsole()
2767 if (groovyConsole == null)
2769 groovyConsole = new groovy.ui.Console();
2770 groovyConsole.setVariable("Jalview", this);
2771 groovyConsole.run();
2774 * We allow only one console at a time, so that AlignFrame menu option
2775 * 'Calculate | Run Groovy script' is unambiguous.
2776 * Disable 'Groovy Console', and enable 'Run script', when the console is
2777 * opened, and the reverse when it is closed
2779 Window window = (Window) groovyConsole.getFrame();
2780 window.addWindowListener(new WindowAdapter()
2783 public void windowClosed(WindowEvent e)
2786 * rebind CMD-Q from Groovy Console to Jalview Quit
2789 enableExecuteGroovy(false);
2795 * show Groovy console window (after close and reopen)
2797 ((Window) groovyConsole.getFrame()).setVisible(true);
2800 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2801 * and disable opening a second console
2803 enableExecuteGroovy(true);
2807 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2808 * binding when opened
2810 protected void addQuitHandler()
2812 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2813 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2814 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2816 getRootPane().getActionMap().put("Quit", new AbstractAction()
2819 public void actionPerformed(ActionEvent e)
2827 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2830 * true if Groovy console is open
2832 public void enableExecuteGroovy(boolean enabled)
2835 * disable opening a second Groovy console
2836 * (or re-enable when the console is closed)
2838 groovyShell.setEnabled(!enabled);
2840 AlignFrame[] alignFrames = getAlignFrames();
2841 if (alignFrames != null)
2843 for (AlignFrame af : alignFrames)
2845 af.setGroovyEnabled(enabled);
2851 * Progress bars managed by the IProgressIndicator method.
2853 private Hashtable<Long, JPanel> progressBars;
2855 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2860 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2863 public void setProgressBar(String message, long id)
2865 if (progressBars == null)
2867 progressBars = new Hashtable<>();
2868 progressBarHandlers = new Hashtable<>();
2871 if (progressBars.get(new Long(id)) != null)
2873 JPanel panel = progressBars.remove(new Long(id));
2874 if (progressBarHandlers.contains(new Long(id)))
2876 progressBarHandlers.remove(new Long(id));
2878 removeProgressPanel(panel);
2882 progressBars.put(new Long(id), addProgressPanel(message));
2889 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2890 * jalview.gui.IProgressIndicatorHandler)
2893 public void registerHandler(final long id,
2894 final IProgressIndicatorHandler handler)
2896 if (progressBarHandlers == null
2897 || !progressBars.containsKey(new Long(id)))
2899 throw new Error(MessageManager.getString(
2900 "error.call_setprogressbar_before_registering_handler"));
2902 progressBarHandlers.put(new Long(id), handler);
2903 final JPanel progressPanel = progressBars.get(new Long(id));
2904 if (handler.canCancel())
2906 JButton cancel = new JButton(
2907 MessageManager.getString("action.cancel"));
2908 final IProgressIndicator us = this;
2909 cancel.addActionListener(new ActionListener()
2913 public void actionPerformed(ActionEvent e)
2915 handler.cancelActivity(id);
2916 us.setProgressBar(MessageManager
2917 .formatMessage("label.cancelled_params", new Object[]
2918 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2922 progressPanel.add(cancel, BorderLayout.EAST);
2928 * @return true if any progress bars are still active
2931 public boolean operationInProgress()
2933 if (progressBars != null && progressBars.size() > 0)
2941 * This will return the first AlignFrame holding the given viewport instance.
2942 * It will break if there are more than one AlignFrames viewing a particular
2946 * @return alignFrame for viewport
2948 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2950 if (desktop != null)
2952 AlignmentPanel[] aps = getAlignmentPanels(
2953 viewport.getSequenceSetId());
2954 for (int panel = 0; aps != null && panel < aps.length; panel++)
2956 if (aps[panel] != null && aps[panel].av == viewport)
2958 return aps[panel].alignFrame;
2965 public VamsasApplication getVamsasApplication()
2972 * flag set if jalview GUI is being operated programmatically
2974 private boolean inBatchMode = false;
2977 * check if jalview GUI is being operated programmatically
2979 * @return inBatchMode
2981 public boolean isInBatchMode()
2987 * set flag if jalview GUI is being operated programmatically
2989 * @param inBatchMode
2991 public void setInBatchMode(boolean inBatchMode)
2993 this.inBatchMode = inBatchMode;
2996 public void startServiceDiscovery()
2998 startServiceDiscovery(false);
3001 public void startServiceDiscovery(boolean blocking)
3003 boolean alive = true;
3004 Thread t0 = null, t1 = null, t2 = null;
3005 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
3008 // todo: changesupport handlers need to be transferred
3009 if (discoverer == null)
3011 discoverer = new jalview.ws.jws1.Discoverer();
3012 // register PCS handler for desktop.
3013 discoverer.addPropertyChangeListener(changeSupport);
3015 // JAL-940 - disabled JWS1 service configuration - always start discoverer
3016 // until we phase out completely
3017 (t0 = new Thread(discoverer)).start();
3020 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
3022 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
3023 .startDiscoverer(changeSupport);
3027 // TODO: do rest service discovery
3036 } catch (Exception e)
3039 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
3040 || (t3 != null && t3.isAlive())
3041 || (t0 != null && t0.isAlive());
3047 * called to check if the service discovery process completed successfully.
3051 protected void JalviewServicesChanged(PropertyChangeEvent evt)
3053 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
3055 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
3056 .getErrorMessages();
3059 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
3061 if (serviceChangedDialog == null)
3063 // only run if we aren't already displaying one of these.
3064 addDialogThread(serviceChangedDialog = new Runnable()
3071 * JalviewDialog jd =new JalviewDialog() {
3073 * @Override protected void cancelPressed() { // TODO
3074 * Auto-generated method stub
3076 * }@Override protected void okPressed() { // TODO
3077 * Auto-generated method stub
3079 * }@Override protected void raiseClosed() { // TODO
3080 * Auto-generated method stub
3082 * } }; jd.initDialogFrame(new
3083 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
3084 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
3085 * + " or mis-configured HTTP proxy settings.<br/>" +
3086 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
3088 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
3089 * ), true, true, "Web Service Configuration Problem", 450,
3092 * jd.waitForInput();
3094 JvOptionPane.showConfirmDialog(Desktop.desktop,
3095 new JLabel("<html><table width=\"450\"><tr><td>"
3096 + ermsg + "</td></tr></table>"
3097 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
3098 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
3099 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
3100 + " Tools->Preferences dialog box to change them.</p></html>"),
3101 "Web Service Configuration Problem",
3102 JvOptionPane.DEFAULT_OPTION,
3103 JvOptionPane.ERROR_MESSAGE);
3104 serviceChangedDialog = null;
3113 "Errors reported by JABA discovery service. Check web services preferences.\n"
3120 private Runnable serviceChangedDialog = null;
3123 * start a thread to open a URL in the configured browser. Pops up a warning
3124 * dialog to the user if there is an exception when calling out to the browser
3129 public static void showUrl(final String url)
3131 showUrl(url, Desktop.instance);
3135 * Like showUrl but allows progress handler to be specified
3139 * (null) or object implementing IProgressIndicator
3141 public static void showUrl(final String url,
3142 final IProgressIndicator progress)
3144 new Thread(new Runnable()
3151 if (progress != null)
3153 progress.setProgressBar(MessageManager
3154 .formatMessage("status.opening_params", new Object[]
3155 { url }), this.hashCode());
3157 jalview.util.BrowserLauncher.openURL(url);
3158 } catch (Exception ex)
3160 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3162 .getString("label.web_browser_not_found_unix"),
3163 MessageManager.getString("label.web_browser_not_found"),
3164 JvOptionPane.WARNING_MESSAGE);
3166 ex.printStackTrace();
3168 if (progress != null)
3170 progress.setProgressBar(null, this.hashCode());
3176 public static WsParamSetManager wsparamManager = null;
3178 public static ParamManager getUserParameterStore()
3180 if (wsparamManager == null)
3182 wsparamManager = new WsParamSetManager();
3184 return wsparamManager;
3188 * static hyperlink handler proxy method for use by Jalview's internal windows
3192 public static void hyperlinkUpdate(HyperlinkEvent e)
3194 if (e.getEventType() == EventType.ACTIVATED)
3199 url = e.getURL().toString();
3200 Desktop.showUrl(url);
3201 } catch (Exception x)
3205 if (Cache.log != null)
3207 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3212 "Couldn't handle string " + url + " as a URL.");
3215 // ignore any exceptions due to dud links.
3222 * single thread that handles display of dialogs to user.
3224 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3227 * flag indicating if dialogExecutor should try to acquire a permit
3229 private volatile boolean dialogPause = true;
3234 private java.util.concurrent.Semaphore block = new Semaphore(0);
3236 private static groovy.ui.Console groovyConsole;
3239 * add another dialog thread to the queue
3243 public void addDialogThread(final Runnable prompter)
3245 dialogExecutor.submit(new Runnable()
3255 } catch (InterruptedException x)
3260 if (instance == null)
3266 SwingUtilities.invokeAndWait(prompter);
3267 } catch (Exception q)
3269 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3275 public void startDialogQueue()
3277 // set the flag so we don't pause waiting for another permit and semaphore
3278 // the current task to begin
3279 dialogPause = false;
3284 protected void snapShotWindow_actionPerformed(ActionEvent e)
3288 ImageMaker im = new jalview.util.ImageMaker(
3289 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3290 getHeight(), of = new File("Jalview_snapshot"
3291 + System.currentTimeMillis() + ".eps"),
3292 "View of desktop", null, 0, false);
3295 paintAll(im.getGraphics());
3297 } catch (Exception q)
3299 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3303 Cache.log.info("Successfully written snapshot to file "
3304 + of.getAbsolutePath());
3308 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3309 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3310 * and location last time the view was expanded (if any). However it does not
3311 * remember the split pane divider location - this is set to match the
3312 * 'exploding' frame.
3316 public void explodeViews(SplitFrame sf)
3318 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3319 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3320 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3322 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3324 int viewCount = topPanels.size();
3331 * Processing in reverse order works, forwards order leaves the first panels
3332 * not visible. I don't know why!
3334 for (int i = viewCount - 1; i >= 0; i--)
3337 * Make new top and bottom frames. These take over the respective
3338 * AlignmentPanel objects, including their AlignmentViewports, so the
3339 * cdna/protein relationships between the viewports is carried over to the
3342 * explodedGeometry holds the (x, y) position of the previously exploded
3343 * SplitFrame, and the (width, height) of the AlignFrame component
3345 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3346 AlignFrame newTopFrame = new AlignFrame(topPanel);
3347 newTopFrame.setSize(oldTopFrame.getSize());
3348 newTopFrame.setVisible(true);
3349 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3350 .getExplodedGeometry();
3351 if (geometry != null)
3353 newTopFrame.setSize(geometry.getSize());
3356 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3357 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3358 newBottomFrame.setSize(oldBottomFrame.getSize());
3359 newBottomFrame.setVisible(true);
3360 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3361 .getExplodedGeometry();
3362 if (geometry != null)
3364 newBottomFrame.setSize(geometry.getSize());
3367 topPanel.av.setGatherViewsHere(false);
3368 bottomPanel.av.setGatherViewsHere(false);
3369 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3371 if (geometry != null)
3373 splitFrame.setLocation(geometry.getLocation());
3375 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3379 * Clear references to the panels (now relocated in the new SplitFrames)
3380 * before closing the old SplitFrame.
3383 bottomPanels.clear();
3388 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3389 * back into the given SplitFrame as additional views. Note that the gathered
3390 * frames may themselves have multiple views.
3394 public void gatherViews(GSplitFrame source)
3397 * special handling of explodedGeometry for a view within a SplitFrame: - it
3398 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3399 * height) of the AlignFrame component
3401 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3402 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3403 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3404 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3405 myBottomFrame.viewport
3406 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3407 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3408 myTopFrame.viewport.setGatherViewsHere(true);
3409 myBottomFrame.viewport.setGatherViewsHere(true);
3410 String topViewId = myTopFrame.viewport.getSequenceSetId();
3411 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3413 JInternalFrame[] frames = desktop.getAllFrames();
3414 for (JInternalFrame frame : frames)
3416 if (frame instanceof SplitFrame && frame != source)
3418 SplitFrame sf = (SplitFrame) frame;
3419 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3420 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3421 boolean gatherThis = false;
3422 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3424 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3425 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3426 if (topViewId.equals(topPanel.av.getSequenceSetId())
3427 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3430 topPanel.av.setGatherViewsHere(false);
3431 bottomPanel.av.setGatherViewsHere(false);
3432 topPanel.av.setExplodedGeometry(
3433 new Rectangle(sf.getLocation(), topFrame.getSize()));
3434 bottomPanel.av.setExplodedGeometry(
3435 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3436 myTopFrame.addAlignmentPanel(topPanel, false);
3437 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3443 topFrame.getAlignPanels().clear();
3444 bottomFrame.getAlignPanels().clear();
3451 * The dust settles...give focus to the tab we did this from.
3453 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3456 public static groovy.ui.Console getGroovyConsole()
3458 return groovyConsole;
3462 * handles the payload of a drag and drop event.
3464 * TODO refactor to desktop utilities class
3467 * - Data source strings extracted from the drop event
3469 * - protocol for each data source extracted from the drop event
3473 * - the payload from the drop event
3476 public static void transferFromDropTarget(List<String> files,
3477 List<DataSourceType> protocols, DropTargetDropEvent evt,
3478 Transferable t) throws Exception
3481 DataFlavor uriListFlavor = new DataFlavor(
3482 "text/uri-list;class=java.lang.String"), urlFlavour = null;
3485 urlFlavour = new DataFlavor(
3486 "application/x-java-url; class=java.net.URL");
3487 } catch (ClassNotFoundException cfe)
3489 Cache.log.debug("Couldn't instantiate the URL dataflavor.", cfe);
3492 if (urlFlavour != null && t.isDataFlavorSupported(urlFlavour))
3497 java.net.URL url = (URL) t.getTransferData(urlFlavour);
3498 // nb: java 8 osx bug https://bugs.openjdk.java.net/browse/JDK-8156099
3499 // means url may be null.
3502 protocols.add(DataSourceType.URL);
3503 files.add(url.toString());
3504 Cache.log.debug("Drop handled as URL dataflavor "
3505 + files.get(files.size() - 1));
3510 if (Platform.isAMac())
3513 "Please ignore plist error - occurs due to problem with java 8 on OSX");
3517 } catch (Throwable ex)
3519 Cache.log.debug("URL drop handler failed.", ex);
3522 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3524 // Works on Windows and MacOSX
3525 Cache.log.debug("Drop handled as javaFileListFlavor");
3526 for (Object file : (List) t
3527 .getTransferData(DataFlavor.javaFileListFlavor))
3529 files.add(((File) file).toString());
3530 protocols.add(DataSourceType.FILE);
3535 // Unix like behaviour
3536 boolean added = false;
3538 if (t.isDataFlavorSupported(uriListFlavor))
3540 Cache.log.debug("Drop handled as uriListFlavor");
3541 // This is used by Unix drag system
3542 data = (String) t.getTransferData(uriListFlavor);
3546 // fallback to text: workaround - on OSX where there's a JVM bug
3547 Cache.log.debug("standard URIListFlavor failed. Trying text");
3548 // try text fallback
3549 DataFlavor textDf = new DataFlavor(
3550 "text/plain;class=java.lang.String");
3551 if (t.isDataFlavorSupported(textDf))
3553 data = (String) t.getTransferData(textDf);
3556 Cache.log.debug("Plain text drop content returned "
3557 + (data == null ? "Null - failed" : data));
3562 while (protocols.size() < files.size())
3564 Cache.log.debug("Adding missing FILE protocol for "
3565 + files.get(protocols.size()));
3566 protocols.add(DataSourceType.FILE);
3568 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3569 data, "\r\n"); st.hasMoreTokens();)
3572 String s = st.nextToken();
3573 if (s.startsWith("#"))
3575 // the line is a comment (as per the RFC 2483)
3578 java.net.URI uri = new java.net.URI(s);
3579 if (uri.getScheme().toLowerCase().startsWith("http"))
3581 protocols.add(DataSourceType.URL);
3582 files.add(uri.toString());
3586 // otherwise preserve old behaviour: catch all for file objects
3587 java.io.File file = new java.io.File(uri);
3588 protocols.add(DataSourceType.FILE);
3589 files.add(file.toString());
3594 if (Cache.log.isDebugEnabled())
3596 if (data == null || !added)
3599 if (t.getTransferDataFlavors() != null
3600 && t.getTransferDataFlavors().length > 0)
3603 "Couldn't resolve drop data. Here are the supported flavors:");
3604 for (DataFlavor fl : t.getTransferDataFlavors())
3607 "Supported transfer dataflavor: " + fl.toString());
3608 Object df = t.getTransferData(fl);
3611 Cache.log.debug("Retrieves: " + df);
3615 Cache.log.debug("Retrieved nothing");
3621 Cache.log.debug("Couldn't resolve dataflavor for drop: "
3627 if (Platform.isWindows())
3630 Cache.log.debug("Scanning dropped content for Windows Link Files");
3632 // resolve any .lnk files in the file drop
3633 for (int f = 0; f < files.size(); f++)
3635 String source = files.get(f).toLowerCase();
3636 if (protocols.get(f).equals(DataSourceType.FILE)
3637 && (source.endsWith(".lnk") || source.endsWith(".url")
3638 || source.endsWith(".site")))
3641 File lf = new File(files.get(f));
3642 // process link file to get a URL
3643 Cache.log.debug("Found potential link file: " + lf);
3644 WindowsShortcut wscfile = new WindowsShortcut(lf);
3645 String fullname = wscfile.getRealFilename();
3646 protocols.set(f, FormatAdapter.checkProtocol(fullname));
3647 files.set(f, fullname);
3648 Cache.log.debug("Parsed real filename " + fullname
3649 + " to extract protocol: " + protocols.get(f));
3651 catch (Exception ex)
3653 Cache.log.error("Couldn't parse "+files.get(f)+" as a link file.",ex);
3661 * Sets the Preferences property for experimental features to True or False
3662 * depending on the state of the controlling menu item
3665 protected void showExperimental_actionPerformed(boolean selected)
3667 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
3671 * Answers a (possibly empty) list of any structure viewer frames (currently
3672 * for either Jmol or Chimera) which are currently open. This may optionally
3673 * be restricted to viewers of a specified class, or viewers linked to a
3674 * specified alignment panel.
3677 * if not null, only return viewers linked to this panel
3678 * @param structureViewerClass
3679 * if not null, only return viewers of this class
3682 public List<StructureViewerBase> getStructureViewers(
3683 AlignmentPanel apanel,
3684 Class<? extends StructureViewerBase> structureViewerClass)
3686 List<StructureViewerBase> result = new ArrayList<>();
3687 JInternalFrame[] frames = Desktop.instance.getAllFrames();
3689 for (JInternalFrame frame : frames)
3691 if (frame instanceof StructureViewerBase)
3693 if (structureViewerClass == null
3694 || structureViewerClass.isInstance(frame))
3697 || ((StructureViewerBase) frame).isLinkedWith(apanel))
3699 result.add((StructureViewerBase) frame);