2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.FocusEvent;
72 import java.awt.event.FocusListener;
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.Box;
97 import javax.swing.BoxLayout;
98 import javax.swing.DefaultDesktopManager;
99 import javax.swing.DesktopManager;
100 import javax.swing.JButton;
101 import javax.swing.JCheckBox;
102 import javax.swing.JComboBox;
103 import javax.swing.JComponent;
104 import javax.swing.JDesktopPane;
105 import javax.swing.JFrame;
106 import javax.swing.JInternalFrame;
107 import javax.swing.JLabel;
108 import javax.swing.JMenuItem;
109 import javax.swing.JPanel;
110 import javax.swing.JPopupMenu;
111 import javax.swing.JProgressBar;
112 import javax.swing.KeyStroke;
113 import javax.swing.SwingUtilities;
114 import javax.swing.event.HyperlinkEvent;
115 import javax.swing.event.HyperlinkEvent.EventType;
116 import javax.swing.event.InternalFrameAdapter;
117 import javax.swing.event.InternalFrameEvent;
118 import javax.swing.event.MenuEvent;
119 import javax.swing.event.MenuListener;
126 * @version $Revision: 1.155 $
128 public class Desktop extends jalview.jbgui.GDesktop
129 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
130 jalview.api.StructureSelectionManagerProvider
132 private static int DEFAULT_MIN_WIDTH = 300;
134 private static int DEFAULT_MIN_HEIGHT = 250;
136 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
138 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
140 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
142 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
145 * news reader - null if it was never started.
147 private BlogReader jvnews = null;
149 private File projectFile;
153 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
155 public void addJalviewPropertyChangeListener(
156 PropertyChangeListener listener)
158 changeSupport.addJalviewPropertyChangeListener(listener);
162 * @param propertyName
164 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
165 * java.beans.PropertyChangeListener)
167 public void addJalviewPropertyChangeListener(String propertyName,
168 PropertyChangeListener listener)
170 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
174 * @param propertyName
176 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
177 * java.beans.PropertyChangeListener)
179 public void removeJalviewPropertyChangeListener(String propertyName,
180 PropertyChangeListener listener)
182 changeSupport.removeJalviewPropertyChangeListener(propertyName,
186 /** Singleton Desktop instance */
187 public static Desktop instance;
189 public static MyDesktopPane desktop;
191 static int openFrameCount = 0;
193 static final int xOffset = 30;
195 static final int yOffset = 30;
197 public static jalview.ws.jws1.Discoverer discoverer;
199 public static Object[] jalviewClipboard;
201 public static boolean internalCopy = false;
203 static int fileLoadingCount = 0;
205 class MyDesktopManager implements DesktopManager
208 private DesktopManager delegate;
210 public MyDesktopManager(DesktopManager delegate)
212 this.delegate = delegate;
216 public void activateFrame(JInternalFrame f)
220 delegate.activateFrame(f);
221 } catch (NullPointerException npe)
223 Point p = getMousePosition();
224 instance.showPasteMenu(p.x, p.y);
229 public void beginDraggingFrame(JComponent f)
231 delegate.beginDraggingFrame(f);
235 public void beginResizingFrame(JComponent f, int direction)
237 delegate.beginResizingFrame(f, direction);
241 public void closeFrame(JInternalFrame f)
243 delegate.closeFrame(f);
247 public void deactivateFrame(JInternalFrame f)
249 delegate.deactivateFrame(f);
253 public void deiconifyFrame(JInternalFrame f)
255 delegate.deiconifyFrame(f);
259 public void dragFrame(JComponent f, int newX, int newY)
265 delegate.dragFrame(f, newX, newY);
269 public void endDraggingFrame(JComponent f)
271 delegate.endDraggingFrame(f);
276 public void endResizingFrame(JComponent f)
278 delegate.endResizingFrame(f);
283 public void iconifyFrame(JInternalFrame f)
285 delegate.iconifyFrame(f);
289 public void maximizeFrame(JInternalFrame f)
291 delegate.maximizeFrame(f);
295 public void minimizeFrame(JInternalFrame f)
297 delegate.minimizeFrame(f);
301 public void openFrame(JInternalFrame f)
303 delegate.openFrame(f);
307 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
314 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
318 public void setBoundsForFrame(JComponent f, int newX, int newY,
319 int newWidth, int newHeight)
321 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
324 // All other methods, simply delegate
329 * Creates a new Desktop object.
334 * A note to implementors. It is ESSENTIAL that any activities that might
335 * block are spawned off as threads rather than waited for during this
339 doVamsasClientCheck();
341 doConfigureStructurePrefs();
342 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
343 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
344 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
346 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
348 desktop = new MyDesktopPane(selmemusage);
349 showMemusage.setSelected(selmemusage);
350 desktop.setBackground(Color.white);
351 getContentPane().setLayout(new BorderLayout());
352 // alternate config - have scrollbars - see notes in JAL-153
353 // JScrollPane sp = new JScrollPane();
354 // sp.getViewport().setView(desktop);
355 // getContentPane().add(sp, BorderLayout.CENTER);
356 getContentPane().add(desktop, BorderLayout.CENTER);
357 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
359 // This line prevents Windows Look&Feel resizing all new windows to maximum
360 // if previous window was maximised
361 desktop.setDesktopManager(
362 new MyDesktopManager(
363 (Platform.isWindows() ? new DefaultDesktopManager()
365 ? new AquaInternalFrameManager()
366 : desktop.getDesktopManager())));
368 Rectangle dims = getLastKnownDimensions("");
375 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
376 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
379 jconsole = new Console(this, showjconsole);
380 // add essential build information
382 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
383 + "\n" + "Jalview Installation: "
384 + jalview.bin.Cache.getDefault("INSTALLATION",
386 + "\n" + "Build Date: "
387 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
388 + "\n" + "Java version: "
389 + System.getProperty("java.version") + "\n"
390 + System.getProperty("os.arch") + " "
391 + System.getProperty("os.name") + " "
392 + System.getProperty("os.version"));
394 showConsole(showjconsole);
396 showNews.setVisible(false);
398 experimentalFeatures.setSelected(showExperimental());
400 getIdentifiersOrgData();
404 this.addWindowListener(new WindowAdapter()
407 public void windowClosing(WindowEvent evt)
414 this.addMouseListener(ma = new MouseAdapter()
417 public void mousePressed(MouseEvent evt)
419 if (evt.isPopupTrigger()) // Mac
421 showPasteMenu(evt.getX(), evt.getY());
426 public void mouseReleased(MouseEvent evt)
428 if (evt.isPopupTrigger()) // Windows
430 showPasteMenu(evt.getX(), evt.getY());
434 desktop.addMouseListener(ma);
436 this.addFocusListener(new FocusListener()
440 public void focusLost(FocusEvent e)
442 // TODO Auto-generated method stub
447 public void focusGained(FocusEvent e)
449 Cache.log.debug("Relaying windows after focus gain");
450 // make sure that we sort windows properly after we gain focus
451 instance.relayerWindows();
454 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
455 // Spawn a thread that shows the splashscreen
456 SwingUtilities.invokeLater(new Runnable()
465 // Thread off a new instance of the file chooser - this reduces the time it
466 // takes to open it later on.
467 new Thread(new Runnable()
472 Cache.log.debug("Filechooser init thread started.");
473 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
474 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
476 Cache.log.debug("Filechooser init thread finished.");
479 // Add the service change listener
480 changeSupport.addJalviewPropertyChangeListener("services",
481 new PropertyChangeListener()
485 public void propertyChange(PropertyChangeEvent evt)
487 Cache.log.debug("Firing service changed event for "
488 + evt.getNewValue());
489 JalviewServicesChanged(evt);
496 * Answers true if user preferences to enable experimental features is True
501 public boolean showExperimental()
503 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
504 Boolean.FALSE.toString());
505 return Boolean.valueOf(experimental).booleanValue();
508 public void doConfigureStructurePrefs()
510 // configure services
511 StructureSelectionManager ssm = StructureSelectionManager
512 .getStructureSelectionManager(this);
513 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
515 ssm.setAddTempFacAnnot(jalview.bin.Cache
516 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
517 ssm.setProcessSecondaryStructure(jalview.bin.Cache
518 .getDefault(Preferences.STRUCT_FROM_PDB, true));
519 ssm.setSecStructServices(
520 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
524 ssm.setAddTempFacAnnot(false);
525 ssm.setProcessSecondaryStructure(false);
526 ssm.setSecStructServices(false);
530 public void checkForNews()
532 final Desktop me = this;
533 // Thread off the news reader, in case there are connection problems.
534 addDialogThread(new Runnable()
539 Cache.log.debug("Starting news thread.");
541 jvnews = new BlogReader(me);
542 showNews.setVisible(true);
543 Cache.log.debug("Completed news thread.");
548 public void getIdentifiersOrgData()
550 // Thread off the identifiers fetcher
551 addDialogThread(new Runnable()
556 Cache.log.debug("Downloading data from identifiers.org");
557 UrlDownloadClient client = new UrlDownloadClient();
560 client.download(IdOrgSettings.getUrl(),
561 IdOrgSettings.getDownloadLocation());
562 } catch (IOException e)
564 Cache.log.debug("Exception downloading identifiers.org data"
572 protected void showNews_actionPerformed(ActionEvent e)
574 showNews(showNews.isSelected());
577 void showNews(boolean visible)
580 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
581 showNews.setSelected(visible);
582 if (visible && !jvnews.isVisible())
584 new Thread(new Runnable()
589 long now = System.currentTimeMillis();
590 Desktop.instance.setProgressBar(
591 MessageManager.getString("status.refreshing_news"),
593 jvnews.refreshNews();
594 Desktop.instance.setProgressBar(null, now);
603 * recover the last known dimensions for a jalview window
606 * - empty string is desktop, all other windows have unique prefix
607 * @return null or last known dimensions scaled to current geometry (if last
608 * window geom was known)
610 Rectangle getLastKnownDimensions(String windowName)
612 // TODO: lock aspect ratio for scaling desktop Bug #0058199
613 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
614 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
615 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
616 String width = jalview.bin.Cache
617 .getProperty(windowName + "SCREEN_WIDTH");
618 String height = jalview.bin.Cache
619 .getProperty(windowName + "SCREEN_HEIGHT");
620 if ((x != null) && (y != null) && (width != null) && (height != null))
622 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
623 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
624 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
626 // attempt #1 - try to cope with change in screen geometry - this
627 // version doesn't preserve original jv aspect ratio.
628 // take ratio of current screen size vs original screen size.
629 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
630 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
631 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
632 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
633 // rescale the bounds depending upon the current screen geometry.
634 ix = (int) (ix * sw);
635 iw = (int) (iw * sw);
636 iy = (int) (iy * sh);
637 ih = (int) (ih * sh);
638 while (ix >= screenSize.width)
640 jalview.bin.Cache.log.debug(
641 "Window geometry location recall error: shifting horizontal to within screenbounds.");
642 ix -= screenSize.width;
644 while (iy >= screenSize.height)
646 jalview.bin.Cache.log.debug(
647 "Window geometry location recall error: shifting vertical to within screenbounds.");
648 iy -= screenSize.height;
650 jalview.bin.Cache.log.debug(
651 "Got last known dimensions for " + windowName + ": x:" + ix
652 + " y:" + iy + " width:" + iw + " height:" + ih);
654 // return dimensions for new instance
655 return new Rectangle(ix, iy, iw, ih);
660 private void doVamsasClientCheck()
662 if (jalview.bin.Cache.vamsasJarsPresent())
664 setupVamsasDisconnectedGui();
665 VamsasMenu.setVisible(true);
666 final Desktop us = this;
667 VamsasMenu.addMenuListener(new MenuListener()
669 // this listener remembers when the menu was first selected, and
670 // doesn't rebuild the session list until it has been cleared and
672 boolean refresh = true;
675 public void menuCanceled(MenuEvent e)
681 public void menuDeselected(MenuEvent e)
687 public void menuSelected(MenuEvent e)
691 us.buildVamsasStMenu();
696 vamsasStart.setVisible(true);
700 void showPasteMenu(int x, int y)
702 JPopupMenu popup = new JPopupMenu();
703 JMenuItem item = new JMenuItem(
704 MessageManager.getString("label.paste_new_window"));
705 item.addActionListener(new ActionListener()
708 public void actionPerformed(ActionEvent evt)
715 popup.show(this, x, y);
722 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
723 Transferable contents = c.getContents(this);
725 if (contents != null)
727 String file = (String) contents
728 .getTransferData(DataFlavor.stringFlavor);
730 FileFormatI format = new IdentifyFile().identify(file,
731 DataSourceType.PASTE);
733 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
736 } catch (Exception ex)
739 "Unable to paste alignment from system clipboard:\n" + ex);
744 * Adds and opens the given frame to the desktop
755 public static synchronized void addInternalFrame(
756 final JInternalFrame frame, String title, int w, int h)
758 addInternalFrame(frame, title, true, w, h, true, false);
762 * Add an internal frame to the Jalview desktop
769 * When true, display frame immediately, otherwise, caller must call
770 * setVisible themselves.
776 public static synchronized void addInternalFrame(
777 final JInternalFrame frame, String title, boolean makeVisible,
780 addInternalFrame(frame, title, makeVisible, w, h, true, false);
784 * Add an internal frame to the Jalview desktop and make it visible
797 public static synchronized void addInternalFrame(
798 final JInternalFrame frame, String title, int w, int h,
801 addInternalFrame(frame, title, true, w, h, resizable, false);
805 * Add an internal frame to the Jalview desktop
812 * When true, display frame immediately, otherwise, caller must call
813 * setVisible themselves.
820 * @param ignoreMinSize
821 * Do not set the default minimum size for frame
823 public static synchronized void addInternalFrame(
824 final JInternalFrame frame, String title, boolean makeVisible,
825 int w, int h, boolean resizable, boolean ignoreMinSize)
828 // TODO: allow callers to determine X and Y position of frame (eg. via
830 // TODO: consider fixing method to update entries in the window submenu with
831 // the current window title
833 frame.setTitle(title);
834 if (frame.getWidth() < 1 || frame.getHeight() < 1)
838 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
839 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
840 // IF JALVIEW IS RUNNING HEADLESS
841 // ///////////////////////////////////////////////
842 if (instance == null || (System.getProperty("java.awt.headless") != null
843 && System.getProperty("java.awt.headless").equals("true")))
852 frame.setMinimumSize(
853 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
855 // Set default dimension for Alignment Frame window.
856 // The Alignment Frame window could be added from a number of places,
858 // I did this here in order not to miss out on any Alignment frame.
859 if (frame instanceof AlignFrame)
861 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
862 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
866 frame.setVisible(makeVisible);
867 frame.setClosable(true);
868 frame.setResizable(resizable);
869 frame.setMaximizable(resizable);
870 frame.setIconifiable(resizable);
872 if (frame.getX() < 1 && frame.getY() < 1)
874 frame.setLocation(xOffset * openFrameCount,
875 yOffset * ((openFrameCount - 1) % 10) + yOffset);
879 * add an entry for the new frame in the Window menu
880 * (and remove it when the frame is closed)
882 final JMenuItem menuItem = new JMenuItem(title);
883 frame.addInternalFrameListener(new InternalFrameAdapter()
886 public void internalFrameActivated(InternalFrameEvent evt)
888 JInternalFrame itf = desktop.getSelectedFrame();
896 public void internalFrameClosed(InternalFrameEvent evt)
898 PaintRefresher.RemoveComponent(frame);
901 * defensive check to prevent frames being
902 * added half off the window
904 if (openFrameCount > 0)
910 * ensure no reference to alignFrame retained by menu item listener
912 if (menuItem.getActionListeners().length > 0)
914 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
916 windowMenu.remove(menuItem);
917 JInternalFrame itf = desktop.getSelectedFrame();
921 if (itf instanceof AlignFrame)
923 Jalview.setCurrentAlignFrame((AlignFrame) itf);
930 menuItem.addActionListener(new ActionListener()
933 public void actionPerformed(ActionEvent e)
937 frame.setSelected(true);
938 frame.setIcon(false);
939 } catch (java.beans.PropertyVetoException ex)
948 windowMenu.add(menuItem);
953 frame.setSelected(true);
954 frame.requestFocus();
955 } catch (java.beans.PropertyVetoException ve)
957 } catch (java.lang.ClassCastException cex)
960 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
966 public void lostOwnership(Clipboard clipboard, Transferable contents)
970 Desktop.jalviewClipboard = null;
973 internalCopy = false;
977 public void dragEnter(DropTargetDragEvent evt)
982 public void dragExit(DropTargetEvent evt)
987 public void dragOver(DropTargetDragEvent evt)
992 public void dropActionChanged(DropTargetDragEvent evt)
1003 public void drop(DropTargetDropEvent evt)
1005 boolean success = true;
1006 // JAL-1552 - acceptDrop required before getTransferable call for
1007 // Java's Transferable for native dnd
1008 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1009 Transferable t = evt.getTransferable();
1010 List<String> files = new ArrayList<>();
1011 List<DataSourceType> protocols = new ArrayList<>();
1015 Desktop.transferFromDropTarget(files, protocols, evt, t);
1016 } catch (Exception e)
1018 e.printStackTrace();
1026 for (int i = 0; i < files.size(); i++)
1028 String file = files.get(i).toString();
1029 DataSourceType protocol = (protocols == null)
1030 ? DataSourceType.FILE
1032 FileFormatI format = null;
1034 if (file.endsWith(".jar"))
1036 format = FileFormat.Jalview;
1041 format = new IdentifyFile().identify(file, protocol);
1044 new FileLoader().LoadFile(file, protocol, format);
1047 } catch (Exception ex)
1052 evt.dropComplete(success); // need this to ensure input focus is properly
1053 // transfered to any new windows created
1063 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1065 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1066 JalviewFileChooser chooser = JalviewFileChooser
1067 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1069 chooser.setFileView(new JalviewFileView());
1070 chooser.setDialogTitle(
1071 MessageManager.getString("label.open_local_file"));
1072 chooser.setToolTipText(MessageManager.getString("action.open"));
1074 int value = chooser.showOpenDialog(this);
1076 if (value == JalviewFileChooser.APPROVE_OPTION)
1078 String choice = chooser.getSelectedFile().getPath();
1079 Cache.setProperty("LAST_DIRECTORY",
1080 chooser.getSelectedFile().getParent());
1082 FileFormatI format = chooser.getSelectedFormat();
1085 * Call IdentifyFile to verify the file contains what its extension implies.
1086 * Skip this step for dynamically added file formats, because
1087 * IdentifyFile does not know how to recognise them.
1089 if (FileFormats.getInstance().isIdentifiable(format))
1093 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1094 } catch (FileFormatException e)
1096 // format = null; //??
1100 if (viewport != null)
1102 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1107 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1119 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1121 // This construct allows us to have a wider textfield
1123 JLabel label = new JLabel(
1124 MessageManager.getString("label.input_file_url"));
1125 final JComboBox history = new JComboBox();
1127 JPanel panel = new JPanel(new GridLayout(2, 1));
1130 history.setPreferredSize(new Dimension(400, 20));
1131 history.setEditable(true);
1132 history.addItem("http://www.");
1134 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1138 if (historyItems != null)
1140 st = new StringTokenizer(historyItems, "\t");
1142 while (st.hasMoreTokens())
1144 history.addItem(st.nextElement());
1148 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1149 MessageManager.getString("label.input_alignment_from_url"),
1150 JvOptionPane.OK_CANCEL_OPTION);
1152 if (reply != JvOptionPane.OK_OPTION)
1157 String url = history.getSelectedItem().toString();
1159 if (url.toLowerCase().endsWith(".jar"))
1161 if (viewport != null)
1163 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1164 FileFormat.Jalview);
1168 new FileLoader().LoadFile(url, DataSourceType.URL,
1169 FileFormat.Jalview);
1174 FileFormatI format = null;
1177 format = new IdentifyFile().identify(url, DataSourceType.URL);
1178 } catch (FileFormatException e)
1180 // TODO revise error handling, distinguish between
1181 // URL not found and response not valid
1186 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1187 MessageManager.formatMessage("label.couldnt_locate",
1190 MessageManager.getString("label.url_not_found"),
1191 JvOptionPane.WARNING_MESSAGE);
1196 if (viewport != null)
1198 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1203 new FileLoader().LoadFile(url, DataSourceType.URL, format);
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);
1418 public void raiseRelated_actionPerformed(ActionEvent e)
1420 reorderAssociatedWindows(false, false);
1424 public void minimizeAssociated_actionPerformed(ActionEvent e)
1426 reorderAssociatedWindows(true, false);
1429 void closeAssociatedWindows()
1431 reorderAssociatedWindows(false, true);
1437 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1441 protected void garbageCollect_actionPerformed(ActionEvent e)
1443 // We simply collect the garbage
1444 jalview.bin.Cache.log.debug("Collecting garbage...");
1446 jalview.bin.Cache.log.debug("Finished garbage collection.");
1453 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1457 protected void showMemusage_actionPerformed(ActionEvent e)
1459 desktop.showMemoryUsage(showMemusage.isSelected());
1466 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1470 protected void showConsole_actionPerformed(ActionEvent e)
1472 showConsole(showConsole.isSelected());
1475 Console jconsole = null;
1478 * control whether the java console is visible or not
1482 void showConsole(boolean selected)
1484 showConsole.setSelected(selected);
1485 // TODO: decide if we should update properties file
1486 Cache.setProperty("SHOW_JAVA_CONSOLE",
1487 Boolean.valueOf(selected).toString());
1488 jconsole.setVisible(selected);
1491 void reorderAssociatedWindows(boolean minimize, boolean close)
1493 JInternalFrame[] frames = desktop.getAllFrames();
1494 if (frames == null || frames.length < 1)
1499 AlignmentViewport source = null, target = null;
1500 if (frames[0] instanceof AlignFrame)
1502 source = ((AlignFrame) frames[0]).getCurrentView();
1504 else if (frames[0] instanceof TreePanel)
1506 source = ((TreePanel) frames[0]).getViewPort();
1508 else if (frames[0] instanceof PCAPanel)
1510 source = ((PCAPanel) frames[0]).av;
1512 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1514 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1519 for (int i = 0; i < frames.length; i++)
1522 if (frames[i] == null)
1526 if (frames[i] instanceof AlignFrame)
1528 target = ((AlignFrame) frames[i]).getCurrentView();
1530 else if (frames[i] instanceof TreePanel)
1532 target = ((TreePanel) frames[i]).getViewPort();
1534 else if (frames[i] instanceof PCAPanel)
1536 target = ((PCAPanel) frames[i]).av;
1538 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1540 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1543 if (source == target)
1549 frames[i].setClosed(true);
1553 frames[i].setIcon(minimize);
1556 frames[i].toFront();
1560 } catch (java.beans.PropertyVetoException ex)
1575 protected void preferences_actionPerformed(ActionEvent e)
1587 public void saveState_actionPerformed(ActionEvent e)
1589 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1592 chooser.setFileView(new JalviewFileView());
1593 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1595 int value = chooser.showSaveDialog(this);
1597 if (value == JalviewFileChooser.APPROVE_OPTION)
1599 final Desktop me = this;
1600 final java.io.File choice = chooser.getSelectedFile();
1601 setProjectFile(choice);
1603 new Thread(new Runnable()
1608 // TODO: refactor to Jalview desktop session controller action.
1609 setProgressBar(MessageManager.formatMessage(
1610 "label.saving_jalview_project", new Object[]
1611 { choice.getName() }), choice.hashCode());
1612 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1613 choice.getParent());
1614 // TODO catch and handle errors for savestate
1615 // TODO prevent user from messing with the Desktop whilst we're saving
1618 new Jalview2XML().saveState(choice);
1619 } catch (OutOfMemoryError oom)
1622 "Whilst saving current state to " + choice.getName(),
1624 } catch (Exception ex)
1627 "Problems whilst trying to save to " + choice.getName(),
1629 JvOptionPane.showMessageDialog(me,
1630 MessageManager.formatMessage(
1631 "label.error_whilst_saving_current_state_to",
1633 { choice.getName() }),
1634 MessageManager.getString("label.couldnt_save_project"),
1635 JvOptionPane.WARNING_MESSAGE);
1637 setProgressBar(null, choice.hashCode());
1643 private void setProjectFile(File choice)
1645 this.projectFile = choice;
1648 public File getProjectFile()
1650 return this.projectFile;
1660 public void loadState_actionPerformed(ActionEvent e)
1662 JalviewFileChooser chooser = new JalviewFileChooser(
1663 Cache.getProperty("LAST_DIRECTORY"), new String[]
1666 { "Jalview Project", "Jalview Project (old)" },
1668 chooser.setFileView(new JalviewFileView());
1669 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1671 int value = chooser.showOpenDialog(this);
1673 if (value == JalviewFileChooser.APPROVE_OPTION)
1675 final File selectedFile = chooser.getSelectedFile();
1676 setProjectFile(selectedFile);
1677 final String choice = selectedFile.getAbsolutePath();
1678 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1679 new Thread(new Runnable()
1684 setProgressBar(MessageManager.formatMessage(
1685 "label.loading_jalview_project", new Object[]
1686 { choice }), choice.hashCode());
1689 new Jalview2XML().loadJalviewAlign(choice);
1690 } catch (OutOfMemoryError oom)
1692 new OOMWarning("Whilst loading project from " + choice, oom);
1693 } catch (Exception ex)
1696 "Problems whilst loading project from " + choice, ex);
1697 JvOptionPane.showMessageDialog(Desktop.desktop,
1698 MessageManager.formatMessage(
1699 "label.error_whilst_loading_project_from",
1702 MessageManager.getString("label.couldnt_load_project"),
1703 JvOptionPane.WARNING_MESSAGE);
1705 setProgressBar(null, choice.hashCode());
1712 public void inputSequence_actionPerformed(ActionEvent e)
1714 new SequenceFetcher(this);
1717 JPanel progressPanel;
1719 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1721 public void startLoading(final String fileName)
1723 if (fileLoadingCount == 0)
1725 fileLoadingPanels.add(addProgressPanel(MessageManager
1726 .formatMessage("label.loading_file", new Object[]
1732 private JPanel addProgressPanel(String string)
1734 if (progressPanel == null)
1736 progressPanel = new JPanel(new GridLayout(1, 1));
1737 totalProgressCount = 0;
1738 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1740 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1741 JProgressBar progressBar = new JProgressBar();
1742 progressBar.setIndeterminate(true);
1744 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1746 thisprogress.add(progressBar, BorderLayout.CENTER);
1747 progressPanel.add(thisprogress);
1748 ((GridLayout) progressPanel.getLayout()).setRows(
1749 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1750 ++totalProgressCount;
1751 instance.validate();
1752 return thisprogress;
1755 int totalProgressCount = 0;
1757 private void removeProgressPanel(JPanel progbar)
1759 if (progressPanel != null)
1761 synchronized (progressPanel)
1763 progressPanel.remove(progbar);
1764 GridLayout gl = (GridLayout) progressPanel.getLayout();
1765 gl.setRows(gl.getRows() - 1);
1766 if (--totalProgressCount < 1)
1768 this.getContentPane().remove(progressPanel);
1769 progressPanel = null;
1776 public void stopLoading()
1779 if (fileLoadingCount < 1)
1781 while (fileLoadingPanels.size() > 0)
1783 removeProgressPanel(fileLoadingPanels.remove(0));
1785 fileLoadingPanels.clear();
1786 fileLoadingCount = 0;
1791 public static int getViewCount(String alignmentId)
1793 AlignmentViewport[] aps = getViewports(alignmentId);
1794 return (aps == null) ? 0 : aps.length;
1799 * @param alignmentId
1800 * - if null, all sets are returned
1801 * @return all AlignmentPanels concerning the alignmentId sequence set
1803 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1805 if (Desktop.desktop == null)
1807 // no frames created and in headless mode
1808 // TODO: verify that frames are recoverable when in headless mode
1811 List<AlignmentPanel> aps = new ArrayList<>();
1812 AlignFrame[] frames = getAlignFrames();
1817 for (AlignFrame af : frames)
1819 for (AlignmentPanel ap : af.alignPanels)
1821 if (alignmentId == null
1822 || alignmentId.equals(ap.av.getSequenceSetId()))
1828 if (aps.size() == 0)
1832 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1837 * get all the viewports on an alignment.
1839 * @param sequenceSetId
1840 * unique alignment id (may be null - all viewports returned in that
1842 * @return all viewports on the alignment bound to sequenceSetId
1844 public static AlignmentViewport[] getViewports(String sequenceSetId)
1846 List<AlignmentViewport> viewp = new ArrayList<>();
1847 if (desktop != null)
1849 AlignFrame[] frames = Desktop.getAlignFrames();
1851 for (AlignFrame afr : frames)
1853 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1854 .equals(sequenceSetId))
1856 if (afr.alignPanels != null)
1858 for (AlignmentPanel ap : afr.alignPanels)
1860 if (sequenceSetId == null
1861 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1869 viewp.add(afr.getViewport());
1873 if (viewp.size() > 0)
1875 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1882 * Explode the views in the given frame into separate AlignFrame
1886 public static void explodeViews(AlignFrame af)
1888 int size = af.alignPanels.size();
1894 for (int i = 0; i < size; i++)
1896 AlignmentPanel ap = af.alignPanels.get(i);
1897 AlignFrame newaf = new AlignFrame(ap);
1900 * Restore the view's last exploded frame geometry if known. Multiple
1901 * views from one exploded frame share and restore the same (frame)
1902 * position and size.
1904 Rectangle geometry = ap.av.getExplodedGeometry();
1905 if (geometry != null)
1907 newaf.setBounds(geometry);
1910 ap.av.setGatherViewsHere(false);
1912 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1913 AlignFrame.DEFAULT_HEIGHT);
1916 af.alignPanels.clear();
1917 af.closeMenuItem_actionPerformed(true);
1922 * Gather expanded views (separate AlignFrame's) with the same sequence set
1923 * identifier back in to this frame as additional views, and close the
1924 * expanded views. Note the expanded frames may themselves have multiple
1925 * views. We take the lot.
1929 public void gatherViews(AlignFrame source)
1931 source.viewport.setGatherViewsHere(true);
1932 source.viewport.setExplodedGeometry(source.getBounds());
1933 JInternalFrame[] frames = desktop.getAllFrames();
1934 String viewId = source.viewport.getSequenceSetId();
1936 for (int t = 0; t < frames.length; t++)
1938 if (frames[t] instanceof AlignFrame && frames[t] != source)
1940 AlignFrame af = (AlignFrame) frames[t];
1941 boolean gatherThis = false;
1942 for (int a = 0; a < af.alignPanels.size(); a++)
1944 AlignmentPanel ap = af.alignPanels.get(a);
1945 if (viewId.equals(ap.av.getSequenceSetId()))
1948 ap.av.setGatherViewsHere(false);
1949 ap.av.setExplodedGeometry(af.getBounds());
1950 source.addAlignmentPanel(ap, false);
1956 af.alignPanels.clear();
1957 af.closeMenuItem_actionPerformed(true);
1964 jalview.gui.VamsasApplication v_client = null;
1967 public void vamsasImport_actionPerformed(ActionEvent e)
1969 if (v_client == null)
1971 // Load and try to start a session.
1972 JalviewFileChooser chooser = new JalviewFileChooser(
1973 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1975 chooser.setFileView(new JalviewFileView());
1976 chooser.setDialogTitle(
1977 MessageManager.getString("label.open_saved_vamsas_session"));
1978 chooser.setToolTipText(MessageManager.getString(
1979 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1981 int value = chooser.showOpenDialog(this);
1983 if (value == JalviewFileChooser.APPROVE_OPTION)
1985 String fle = chooser.getSelectedFile().toString();
1986 if (!vamsasImport(chooser.getSelectedFile()))
1988 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1989 MessageManager.formatMessage(
1990 "label.couldnt_import_as_vamsas_session",
1994 .getString("label.vamsas_document_import_failed"),
1995 JvOptionPane.ERROR_MESSAGE);
2001 jalview.bin.Cache.log.error(
2002 "Implementation error - load session from a running session is not supported.");
2007 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2010 * @return true if import was a success and a session was started.
2012 public boolean vamsasImport(URL url)
2014 // TODO: create progress bar
2015 if (v_client != null)
2018 jalview.bin.Cache.log.error(
2019 "Implementation error - load session from a running session is not supported.");
2025 // copy the URL content to a temporary local file
2026 // TODO: be a bit cleverer here with nio (?!)
2027 File file = File.createTempFile("vdocfromurl", ".vdj");
2028 FileOutputStream fos = new FileOutputStream(file);
2029 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2030 byte[] buffer = new byte[2048];
2032 while ((ln = bis.read(buffer)) > -1)
2034 fos.write(buffer, 0, ln);
2038 v_client = new jalview.gui.VamsasApplication(this, file,
2039 url.toExternalForm());
2040 } catch (Exception ex)
2042 jalview.bin.Cache.log.error(
2043 "Failed to create new vamsas session from contents of URL "
2048 setupVamsasConnectedGui();
2049 v_client.initial_update(); // TODO: thread ?
2050 return v_client.inSession();
2054 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2057 * @return true if import was a success and a session was started.
2059 public boolean vamsasImport(File file)
2061 if (v_client != null)
2064 jalview.bin.Cache.log.error(
2065 "Implementation error - load session from a running session is not supported.");
2069 setProgressBar(MessageManager.formatMessage(
2070 "status.importing_vamsas_session_from", new Object[]
2071 { file.getName() }), file.hashCode());
2074 v_client = new jalview.gui.VamsasApplication(this, file, null);
2075 } catch (Exception ex)
2077 setProgressBar(MessageManager.formatMessage(
2078 "status.importing_vamsas_session_from", new Object[]
2079 { file.getName() }), file.hashCode());
2080 jalview.bin.Cache.log.error(
2081 "New vamsas session from existing session file failed:", ex);
2084 setupVamsasConnectedGui();
2085 v_client.initial_update(); // TODO: thread ?
2086 setProgressBar(MessageManager.formatMessage(
2087 "status.importing_vamsas_session_from", new Object[]
2088 { file.getName() }), file.hashCode());
2089 return v_client.inSession();
2092 public boolean joinVamsasSession(String mysesid)
2094 if (v_client != null)
2096 throw new Error(MessageManager
2097 .getString("error.try_join_vamsas_session_another"));
2099 if (mysesid == null)
2102 MessageManager.getString("error.invalid_vamsas_session_id"));
2104 v_client = new VamsasApplication(this, mysesid);
2105 setupVamsasConnectedGui();
2106 v_client.initial_update();
2107 return (v_client.inSession());
2111 public void vamsasStart_actionPerformed(ActionEvent e)
2113 if (v_client == null)
2116 // we just start a default session for moment.
2118 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2119 * getProperty("LAST_DIRECTORY"));
2121 * chooser.setFileView(new JalviewFileView());
2122 * chooser.setDialogTitle("Load Vamsas file");
2123 * chooser.setToolTipText("Import");
2125 * int value = chooser.showOpenDialog(this);
2127 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2128 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2130 v_client = new VamsasApplication(this);
2131 setupVamsasConnectedGui();
2132 v_client.initial_update(); // TODO: thread ?
2136 // store current data in session.
2137 v_client.push_update(); // TODO: thread
2141 protected void setupVamsasConnectedGui()
2143 vamsasStart.setText(MessageManager.getString("label.session_update"));
2144 vamsasSave.setVisible(true);
2145 vamsasStop.setVisible(true);
2146 vamsasImport.setVisible(false); // Document import to existing session is
2147 // not possible for vamsas-client-1.0.
2150 protected void setupVamsasDisconnectedGui()
2152 vamsasSave.setVisible(false);
2153 vamsasStop.setVisible(false);
2154 vamsasImport.setVisible(true);
2156 .setText(MessageManager.getString("label.new_vamsas_session"));
2160 public void vamsasStop_actionPerformed(ActionEvent e)
2162 if (v_client != null)
2164 v_client.end_session();
2166 setupVamsasDisconnectedGui();
2170 protected void buildVamsasStMenu()
2172 if (v_client == null)
2174 String[] sess = null;
2177 sess = VamsasApplication.getSessionList();
2178 } catch (Exception e)
2180 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2186 jalview.bin.Cache.log.debug(
2187 "Got current sessions list: " + sess.length + " entries.");
2188 VamsasStMenu.removeAll();
2189 for (int i = 0; i < sess.length; i++)
2191 JMenuItem sessit = new JMenuItem();
2192 sessit.setText(sess[i]);
2193 sessit.setToolTipText(MessageManager
2194 .formatMessage("label.connect_to_session", new Object[]
2196 final Desktop dsktp = this;
2197 final String mysesid = sess[i];
2198 sessit.addActionListener(new ActionListener()
2202 public void actionPerformed(ActionEvent e)
2204 if (dsktp.v_client == null)
2206 Thread rthr = new Thread(new Runnable()
2212 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2213 dsktp.setupVamsasConnectedGui();
2214 dsktp.v_client.initial_update();
2222 VamsasStMenu.add(sessit);
2224 // don't show an empty menu.
2225 VamsasStMenu.setVisible(sess.length > 0);
2230 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2231 VamsasStMenu.removeAll();
2232 VamsasStMenu.setVisible(false);
2237 // Not interested in the content. Just hide ourselves.
2238 VamsasStMenu.setVisible(false);
2243 public void vamsasSave_actionPerformed(ActionEvent e)
2245 if (v_client != null)
2247 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2248 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2251 chooser.setFileView(new JalviewFileView());
2252 chooser.setDialogTitle(MessageManager
2253 .getString("label.save_vamsas_document_archive"));
2255 int value = chooser.showSaveDialog(this);
2257 if (value == JalviewFileChooser.APPROVE_OPTION)
2259 java.io.File choice = chooser.getSelectedFile();
2260 JPanel progpanel = addProgressPanel(MessageManager
2261 .formatMessage("label.saving_vamsas_doc", new Object[]
2262 { choice.getName() }));
2263 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2264 String warnmsg = null;
2265 String warnttl = null;
2268 v_client.vclient.storeDocument(choice);
2271 warnttl = "Serious Problem saving Vamsas Document";
2272 warnmsg = ex.toString();
2273 jalview.bin.Cache.log
2274 .error("Error Whilst saving document to " + choice, ex);
2276 } catch (Exception ex)
2278 warnttl = "Problem saving Vamsas Document.";
2279 warnmsg = ex.toString();
2280 jalview.bin.Cache.log.warn(
2281 "Exception Whilst saving document to " + choice, ex);
2284 removeProgressPanel(progpanel);
2285 if (warnmsg != null)
2287 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2289 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2295 JPanel vamUpdate = null;
2298 * hide vamsas user gui bits when a vamsas document event is being handled.
2301 * true to hide gui, false to reveal gui
2303 public void setVamsasUpdate(boolean b)
2305 Cache.log.debug("Setting gui for Vamsas update "
2306 + (b ? "in progress" : "finished"));
2308 if (vamUpdate != null)
2310 this.removeProgressPanel(vamUpdate);
2314 vamUpdate = this.addProgressPanel(
2315 MessageManager.getString("label.updating_vamsas_session"));
2317 vamsasStart.setVisible(!b);
2318 vamsasStop.setVisible(!b);
2319 vamsasSave.setVisible(!b);
2322 public JInternalFrame[] getAllFrames()
2324 return desktop.getAllFrames();
2328 * Checks the given url to see if it gives a response indicating that the user
2329 * should be informed of a new questionnaire.
2333 public void checkForQuestionnaire(String url)
2335 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2336 // javax.swing.SwingUtilities.invokeLater(jvq);
2337 new Thread(jvq).start();
2340 public void checkURLLinks()
2342 // Thread off the URL link checker
2343 addDialogThread(new Runnable()
2348 if (Cache.getDefault("CHECKURLLINKS", true))
2350 // check what the actual links are - if it's just the default don't
2351 // bother with the warning
2352 List<String> links = Preferences.sequenceUrlLinks
2355 // only need to check links if there is one with a
2356 // SEQUENCE_ID which is not the default EMBL_EBI link
2357 ListIterator<String> li = links.listIterator();
2358 boolean check = false;
2359 List<JLabel> urls = new ArrayList<>();
2360 while (li.hasNext())
2362 String link = li.next();
2363 if (link.contains(SEQUENCE_ID)
2364 && !link.equals(UrlConstants.DEFAULT_STRING))
2367 int barPos = link.indexOf("|");
2368 String urlMsg = barPos == -1 ? link
2369 : link.substring(0, barPos) + ": "
2370 + link.substring(barPos + 1);
2371 urls.add(new JLabel(urlMsg));
2379 // ask user to check in case URL links use old style tokens
2380 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2381 JPanel msgPanel = new JPanel();
2382 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2383 msgPanel.add(Box.createVerticalGlue());
2384 JLabel msg = new JLabel(MessageManager
2385 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2386 JLabel msg2 = new JLabel(MessageManager
2387 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2389 for (JLabel url : urls)
2395 final JCheckBox jcb = new JCheckBox(
2396 MessageManager.getString("label.do_not_display_again"));
2397 jcb.addActionListener(new ActionListener()
2400 public void actionPerformed(ActionEvent e)
2402 // update Cache settings for "don't show this again"
2403 boolean showWarningAgain = !jcb.isSelected();
2404 Cache.setProperty("CHECKURLLINKS",
2405 Boolean.valueOf(showWarningAgain).toString());
2410 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2412 .getString("label.SEQUENCE_ID_no_longer_used"),
2413 JvOptionPane.WARNING_MESSAGE);
2420 * Proxy class for JDesktopPane which optionally displays the current memory
2421 * usage and highlights the desktop area with a red bar if free memory runs
2426 public class MyDesktopPane extends JDesktopPane implements Runnable
2429 private static final float ONE_MB = 1048576f;
2431 boolean showMemoryUsage = false;
2435 java.text.NumberFormat df;
2437 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2440 public MyDesktopPane(boolean showMemoryUsage)
2442 showMemoryUsage(showMemoryUsage);
2445 public void showMemoryUsage(boolean showMemory)
2447 this.showMemoryUsage = showMemory;
2450 Thread worker = new Thread(this);
2456 public boolean isShowMemoryUsage()
2458 return showMemoryUsage;
2464 df = java.text.NumberFormat.getNumberInstance();
2465 df.setMaximumFractionDigits(2);
2466 runtime = Runtime.getRuntime();
2468 while (showMemoryUsage)
2472 maxMemory = runtime.maxMemory() / ONE_MB;
2473 allocatedMemory = runtime.totalMemory() / ONE_MB;
2474 freeMemory = runtime.freeMemory() / ONE_MB;
2475 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2477 percentUsage = (totalFreeMemory / maxMemory) * 100;
2479 // if (percentUsage < 20)
2481 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2483 // instance.set.setBorder(border1);
2486 // sleep after showing usage
2488 } catch (Exception ex)
2490 ex.printStackTrace();
2496 public void paintComponent(Graphics g)
2498 if (showMemoryUsage && g != null && df != null)
2500 if (percentUsage < 20)
2502 g.setColor(Color.red);
2504 FontMetrics fm = g.getFontMetrics();
2507 g.drawString(MessageManager.formatMessage("label.memory_stats",
2509 { df.format(totalFreeMemory), df.format(maxMemory),
2510 df.format(percentUsage) }),
2511 10, getHeight() - fm.getHeight());
2518 * fixes stacking order after a modal dialog to ensure windows that should be
2519 * on top actually are
2521 public void relayerWindows()
2527 * Accessor method to quickly get all the AlignmentFrames loaded.
2529 * @return an array of AlignFrame, or null if none found
2531 public static AlignFrame[] getAlignFrames()
2533 if (Jalview.isHeadlessMode())
2535 // Desktop.desktop is null in headless mode
2536 return new AlignFrame[] { Jalview.currentAlignFrame };
2539 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2545 List<AlignFrame> avp = new ArrayList<>();
2547 for (int i = frames.length - 1; i > -1; i--)
2549 if (frames[i] instanceof AlignFrame)
2551 avp.add((AlignFrame) frames[i]);
2553 else if (frames[i] instanceof SplitFrame)
2556 * Also check for a split frame containing an AlignFrame
2558 GSplitFrame sf = (GSplitFrame) frames[i];
2559 if (sf.getTopFrame() instanceof AlignFrame)
2561 avp.add((AlignFrame) sf.getTopFrame());
2563 if (sf.getBottomFrame() instanceof AlignFrame)
2565 avp.add((AlignFrame) sf.getBottomFrame());
2569 if (avp.size() == 0)
2573 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2578 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2582 public GStructureViewer[] getJmols()
2584 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2590 List<GStructureViewer> avp = new ArrayList<>();
2592 for (int i = frames.length - 1; i > -1; i--)
2594 if (frames[i] instanceof AppJmol)
2596 GStructureViewer af = (GStructureViewer) frames[i];
2600 if (avp.size() == 0)
2604 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2609 * Add Groovy Support to Jalview
2612 public void groovyShell_actionPerformed()
2616 openGroovyConsole();
2617 } catch (Exception ex)
2619 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2620 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2622 MessageManager.getString("label.couldnt_create_groovy_shell"),
2623 MessageManager.getString("label.groovy_support_failed"),
2624 JvOptionPane.ERROR_MESSAGE);
2629 * Open the Groovy console
2631 void openGroovyConsole()
2633 if (groovyConsole == null)
2635 groovyConsole = new groovy.ui.Console();
2636 groovyConsole.setVariable("Jalview", this);
2637 groovyConsole.run();
2640 * We allow only one console at a time, so that AlignFrame menu option
2641 * 'Calculate | Run Groovy script' is unambiguous.
2642 * Disable 'Groovy Console', and enable 'Run script', when the console is
2643 * opened, and the reverse when it is closed
2645 Window window = (Window) groovyConsole.getFrame();
2646 window.addWindowListener(new WindowAdapter()
2649 public void windowClosed(WindowEvent e)
2652 * rebind CMD-Q from Groovy Console to Jalview Quit
2655 enableExecuteGroovy(false);
2661 * show Groovy console window (after close and reopen)
2663 ((Window) groovyConsole.getFrame()).setVisible(true);
2666 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2667 * and disable opening a second console
2669 enableExecuteGroovy(true);
2673 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2674 * binding when opened
2676 protected void addQuitHandler()
2678 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2679 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2680 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2682 getRootPane().getActionMap().put("Quit", new AbstractAction()
2685 public void actionPerformed(ActionEvent e)
2693 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2696 * true if Groovy console is open
2698 public void enableExecuteGroovy(boolean enabled)
2701 * disable opening a second Groovy console
2702 * (or re-enable when the console is closed)
2704 groovyShell.setEnabled(!enabled);
2706 AlignFrame[] alignFrames = getAlignFrames();
2707 if (alignFrames != null)
2709 for (AlignFrame af : alignFrames)
2711 af.setGroovyEnabled(enabled);
2717 * Progress bars managed by the IProgressIndicator method.
2719 private Hashtable<Long, JPanel> progressBars;
2721 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2726 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2729 public void setProgressBar(String message, long id)
2731 if (progressBars == null)
2733 progressBars = new Hashtable<>();
2734 progressBarHandlers = new Hashtable<>();
2737 if (progressBars.get(new Long(id)) != null)
2739 JPanel panel = progressBars.remove(new Long(id));
2740 if (progressBarHandlers.contains(new Long(id)))
2742 progressBarHandlers.remove(new Long(id));
2744 removeProgressPanel(panel);
2748 progressBars.put(new Long(id), addProgressPanel(message));
2755 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2756 * jalview.gui.IProgressIndicatorHandler)
2759 public void registerHandler(final long id,
2760 final IProgressIndicatorHandler handler)
2762 if (progressBarHandlers == null
2763 || !progressBars.containsKey(new Long(id)))
2765 throw new Error(MessageManager.getString(
2766 "error.call_setprogressbar_before_registering_handler"));
2768 progressBarHandlers.put(new Long(id), handler);
2769 final JPanel progressPanel = progressBars.get(new Long(id));
2770 if (handler.canCancel())
2772 JButton cancel = new JButton(
2773 MessageManager.getString("action.cancel"));
2774 final IProgressIndicator us = this;
2775 cancel.addActionListener(new ActionListener()
2779 public void actionPerformed(ActionEvent e)
2781 handler.cancelActivity(id);
2782 us.setProgressBar(MessageManager
2783 .formatMessage("label.cancelled_params", new Object[]
2784 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2788 progressPanel.add(cancel, BorderLayout.EAST);
2794 * @return true if any progress bars are still active
2797 public boolean operationInProgress()
2799 if (progressBars != null && progressBars.size() > 0)
2807 * This will return the first AlignFrame holding the given viewport instance.
2808 * It will break if there are more than one AlignFrames viewing a particular
2812 * @return alignFrame for viewport
2814 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2816 if (desktop != null)
2818 AlignmentPanel[] aps = getAlignmentPanels(
2819 viewport.getSequenceSetId());
2820 for (int panel = 0; aps != null && panel < aps.length; panel++)
2822 if (aps[panel] != null && aps[panel].av == viewport)
2824 return aps[panel].alignFrame;
2831 public VamsasApplication getVamsasApplication()
2838 * flag set if jalview GUI is being operated programmatically
2840 private boolean inBatchMode = false;
2843 * check if jalview GUI is being operated programmatically
2845 * @return inBatchMode
2847 public boolean isInBatchMode()
2853 * set flag if jalview GUI is being operated programmatically
2855 * @param inBatchMode
2857 public void setInBatchMode(boolean inBatchMode)
2859 this.inBatchMode = inBatchMode;
2862 public void startServiceDiscovery()
2864 startServiceDiscovery(false);
2867 public void startServiceDiscovery(boolean blocking)
2869 boolean alive = true;
2870 Thread t0 = null, t1 = null, t2 = null;
2871 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2874 // todo: changesupport handlers need to be transferred
2875 if (discoverer == null)
2877 discoverer = new jalview.ws.jws1.Discoverer();
2878 // register PCS handler for desktop.
2879 discoverer.addPropertyChangeListener(changeSupport);
2881 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2882 // until we phase out completely
2883 (t0 = new Thread(discoverer)).start();
2886 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2888 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2889 .startDiscoverer(changeSupport);
2893 // TODO: do rest service discovery
2902 } catch (Exception e)
2905 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2906 || (t3 != null && t3.isAlive())
2907 || (t0 != null && t0.isAlive());
2913 * called to check if the service discovery process completed successfully.
2917 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2919 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2921 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2922 .getErrorMessages();
2925 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2927 if (serviceChangedDialog == null)
2929 // only run if we aren't already displaying one of these.
2930 addDialogThread(serviceChangedDialog = new Runnable()
2937 * JalviewDialog jd =new JalviewDialog() {
2939 * @Override protected void cancelPressed() { // TODO
2940 * Auto-generated method stub
2942 * }@Override protected void okPressed() { // TODO
2943 * Auto-generated method stub
2945 * }@Override protected void raiseClosed() { // TODO
2946 * Auto-generated method stub
2948 * } }; jd.initDialogFrame(new
2949 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2950 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2951 * + " or mis-configured HTTP proxy settings.<br/>" +
2952 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2954 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2955 * ), true, true, "Web Service Configuration Problem", 450,
2958 * jd.waitForInput();
2960 JvOptionPane.showConfirmDialog(Desktop.desktop,
2961 new JLabel("<html><table width=\"450\"><tr><td>"
2962 + ermsg + "</td></tr></table>"
2963 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2964 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2965 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2966 + " Tools->Preferences dialog box to change them.</p></html>"),
2967 "Web Service Configuration Problem",
2968 JvOptionPane.DEFAULT_OPTION,
2969 JvOptionPane.ERROR_MESSAGE);
2970 serviceChangedDialog = null;
2979 "Errors reported by JABA discovery service. Check web services preferences.\n"
2986 private Runnable serviceChangedDialog = null;
2989 * start a thread to open a URL in the configured browser. Pops up a warning
2990 * dialog to the user if there is an exception when calling out to the browser
2995 public static void showUrl(final String url)
2997 showUrl(url, Desktop.instance);
3001 * Like showUrl but allows progress handler to be specified
3005 * (null) or object implementing IProgressIndicator
3007 public static void showUrl(final String url,
3008 final IProgressIndicator progress)
3010 new Thread(new Runnable()
3017 if (progress != null)
3019 progress.setProgressBar(MessageManager
3020 .formatMessage("status.opening_params", new Object[]
3021 { url }), this.hashCode());
3023 jalview.util.BrowserLauncher.openURL(url);
3024 } catch (Exception ex)
3026 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3028 .getString("label.web_browser_not_found_unix"),
3029 MessageManager.getString("label.web_browser_not_found"),
3030 JvOptionPane.WARNING_MESSAGE);
3032 ex.printStackTrace();
3034 if (progress != null)
3036 progress.setProgressBar(null, this.hashCode());
3042 public static WsParamSetManager wsparamManager = null;
3044 public static ParamManager getUserParameterStore()
3046 if (wsparamManager == null)
3048 wsparamManager = new WsParamSetManager();
3050 return wsparamManager;
3054 * static hyperlink handler proxy method for use by Jalview's internal windows
3058 public static void hyperlinkUpdate(HyperlinkEvent e)
3060 if (e.getEventType() == EventType.ACTIVATED)
3065 url = e.getURL().toString();
3066 Desktop.showUrl(url);
3067 } catch (Exception x)
3071 if (Cache.log != null)
3073 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3078 "Couldn't handle string " + url + " as a URL.");
3081 // ignore any exceptions due to dud links.
3088 * single thread that handles display of dialogs to user.
3090 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3093 * flag indicating if dialogExecutor should try to acquire a permit
3095 private volatile boolean dialogPause = true;
3100 private java.util.concurrent.Semaphore block = new Semaphore(0);
3102 private static groovy.ui.Console groovyConsole;
3105 * add another dialog thread to the queue
3109 public void addDialogThread(final Runnable prompter)
3111 dialogExecutor.submit(new Runnable()
3121 } catch (InterruptedException x)
3126 if (instance == null)
3132 SwingUtilities.invokeAndWait(prompter);
3133 } catch (Exception q)
3135 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3141 public void startDialogQueue()
3143 // set the flag so we don't pause waiting for another permit and semaphore
3144 // the current task to begin
3145 dialogPause = false;
3150 protected void snapShotWindow_actionPerformed(ActionEvent e)
3154 ImageMaker im = new jalview.util.ImageMaker(
3155 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3156 getHeight(), of = new File("Jalview_snapshot"
3157 + System.currentTimeMillis() + ".eps"),
3158 "View of desktop", null, 0, false);
3161 paintAll(im.getGraphics());
3163 } catch (Exception q)
3165 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3169 Cache.log.info("Successfully written snapshot to file "
3170 + of.getAbsolutePath());
3174 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3175 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3176 * and location last time the view was expanded (if any). However it does not
3177 * remember the split pane divider location - this is set to match the
3178 * 'exploding' frame.
3182 public void explodeViews(SplitFrame sf)
3184 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3185 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3186 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3188 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3190 int viewCount = topPanels.size();
3197 * Processing in reverse order works, forwards order leaves the first panels
3198 * not visible. I don't know why!
3200 for (int i = viewCount - 1; i >= 0; i--)
3203 * Make new top and bottom frames. These take over the respective
3204 * AlignmentPanel objects, including their AlignmentViewports, so the
3205 * cdna/protein relationships between the viewports is carried over to the
3208 * explodedGeometry holds the (x, y) position of the previously exploded
3209 * SplitFrame, and the (width, height) of the AlignFrame component
3211 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3212 AlignFrame newTopFrame = new AlignFrame(topPanel);
3213 newTopFrame.setSize(oldTopFrame.getSize());
3214 newTopFrame.setVisible(true);
3215 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3216 .getExplodedGeometry();
3217 if (geometry != null)
3219 newTopFrame.setSize(geometry.getSize());
3222 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3223 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3224 newBottomFrame.setSize(oldBottomFrame.getSize());
3225 newBottomFrame.setVisible(true);
3226 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3227 .getExplodedGeometry();
3228 if (geometry != null)
3230 newBottomFrame.setSize(geometry.getSize());
3233 topPanel.av.setGatherViewsHere(false);
3234 bottomPanel.av.setGatherViewsHere(false);
3235 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3237 if (geometry != null)
3239 splitFrame.setLocation(geometry.getLocation());
3241 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3245 * Clear references to the panels (now relocated in the new SplitFrames)
3246 * before closing the old SplitFrame.
3249 bottomPanels.clear();
3254 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3255 * back into the given SplitFrame as additional views. Note that the gathered
3256 * frames may themselves have multiple views.
3260 public void gatherViews(GSplitFrame source)
3263 * special handling of explodedGeometry for a view within a SplitFrame: - it
3264 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3265 * height) of the AlignFrame component
3267 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3268 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3269 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3270 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3271 myBottomFrame.viewport
3272 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3273 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3274 myTopFrame.viewport.setGatherViewsHere(true);
3275 myBottomFrame.viewport.setGatherViewsHere(true);
3276 String topViewId = myTopFrame.viewport.getSequenceSetId();
3277 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3279 JInternalFrame[] frames = desktop.getAllFrames();
3280 for (JInternalFrame frame : frames)
3282 if (frame instanceof SplitFrame && frame != source)
3284 SplitFrame sf = (SplitFrame) frame;
3285 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3286 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3287 boolean gatherThis = false;
3288 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3290 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3291 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3292 if (topViewId.equals(topPanel.av.getSequenceSetId())
3293 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3296 topPanel.av.setGatherViewsHere(false);
3297 bottomPanel.av.setGatherViewsHere(false);
3298 topPanel.av.setExplodedGeometry(
3299 new Rectangle(sf.getLocation(), topFrame.getSize()));
3300 bottomPanel.av.setExplodedGeometry(
3301 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3302 myTopFrame.addAlignmentPanel(topPanel, false);
3303 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3309 topFrame.getAlignPanels().clear();
3310 bottomFrame.getAlignPanels().clear();
3317 * The dust settles...give focus to the tab we did this from.
3319 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3322 public static groovy.ui.Console getGroovyConsole()
3324 return groovyConsole;
3327 public static void transferFromDropTarget(List<String> files,
3328 List<DataSourceType> protocols, DropTargetDropEvent evt,
3329 Transferable t) throws Exception
3332 DataFlavor uriListFlavor = new DataFlavor(
3333 "text/uri-list;class=java.lang.String");
3334 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3336 // Works on Windows and MacOSX
3337 Cache.log.debug("Drop handled as javaFileListFlavor");
3338 for (Object file : (List) t
3339 .getTransferData(DataFlavor.javaFileListFlavor))
3341 files.add(((File) file).toString());
3342 protocols.add(DataSourceType.FILE);
3347 // Unix like behaviour
3348 boolean added = false;
3350 if (t.isDataFlavorSupported(uriListFlavor))
3352 Cache.log.debug("Drop handled as uriListFlavor");
3353 // This is used by Unix drag system
3354 data = (String) t.getTransferData(uriListFlavor);
3358 // fallback to text: workaround - on OSX where there's a JVM bug
3359 Cache.log.debug("standard URIListFlavor failed. Trying text");
3360 // try text fallback
3361 data = (String) t.getTransferData(
3362 new DataFlavor("text/plain;class=java.lang.String"));
3363 if (Cache.log.isDebugEnabled())
3365 Cache.log.debug("fallback returned " + data);
3368 while (protocols.size() < files.size())
3370 Cache.log.debug("Adding missing FILE protocol for "
3371 + files.get(protocols.size()));
3372 protocols.add(DataSourceType.FILE);
3374 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3375 data, "\r\n"); st.hasMoreTokens();)
3378 String s = st.nextToken();
3379 if (s.startsWith("#"))
3381 // the line is a comment (as per the RFC 2483)
3384 java.net.URI uri = new java.net.URI(s);
3385 if (uri.getScheme().toLowerCase().startsWith("http"))
3387 protocols.add(DataSourceType.URL);
3388 files.add(uri.toString());
3392 // otherwise preserve old behaviour: catch all for file objects
3393 java.io.File file = new java.io.File(uri);
3394 protocols.add(DataSourceType.FILE);
3395 files.add(file.toString());
3398 if (Cache.log.isDebugEnabled())
3400 if (data == null || !added)
3403 "Couldn't resolve drop data. Here are the supported flavors:");
3404 for (DataFlavor fl : t.getTransferDataFlavors())
3407 "Supported transfer dataflavor: " + fl.toString());
3408 Object df = t.getTransferData(fl);
3411 Cache.log.debug("Retrieves: " + df);
3415 Cache.log.debug("Retrieved nothing");
3424 * Sets the Preferences property for experimental features to True or False
3425 * depending on the state of the controlling menu item
3428 protected void showExperimental_actionPerformed(boolean selected)
3430 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));