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 implements
129 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);
275 public void endResizingFrame(JComponent f)
277 delegate.endResizingFrame(f);
281 public void iconifyFrame(JInternalFrame f)
283 delegate.iconifyFrame(f);
287 public void maximizeFrame(JInternalFrame f)
289 delegate.maximizeFrame(f);
293 public void minimizeFrame(JInternalFrame f)
295 delegate.minimizeFrame(f);
299 public void openFrame(JInternalFrame f)
301 delegate.openFrame(f);
305 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
312 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
316 public void setBoundsForFrame(JComponent f, int newX, int newY,
317 int newWidth, int newHeight)
319 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
322 // All other methods, simply delegate
327 * Creates a new Desktop object.
332 * A note to implementors. It is ESSENTIAL that any activities that might
333 * block are spawned off as threads rather than waited for during this
337 doVamsasClientCheck();
339 doConfigureStructurePrefs();
340 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
341 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
342 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
344 boolean showjconsole = jalview.bin.Cache.getDefault(
345 "SHOW_JAVA_CONSOLE", false);
346 desktop = new MyDesktopPane(selmemusage);
347 if (Platform.isAMac())
349 desktop.setDoubleBuffered(false);
351 showMemusage.setSelected(selmemusage);
352 desktop.setBackground(Color.white);
353 getContentPane().setLayout(new BorderLayout());
354 // alternate config - have scrollbars - see notes in JAL-153
355 // JScrollPane sp = new JScrollPane();
356 // sp.getViewport().setView(desktop);
357 // getContentPane().add(sp, BorderLayout.CENTER);
358 getContentPane().add(desktop, BorderLayout.CENTER);
359 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
361 // This line prevents Windows Look&Feel resizing all new windows to maximum
362 // if previous window was maximised
363 desktop.setDesktopManager(new MyDesktopManager(
364 new DefaultDesktopManager()));
366 Rectangle dims = getLastKnownDimensions("");
373 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
374 setBounds((screenSize.width - 900) / 2,
375 (screenSize.height - 650) / 2, 900, 650);
377 jconsole = new Console(this, showjconsole);
378 // add essential build information
379 jconsole.setHeader("Jalview Version: "
380 + jalview.bin.Cache.getProperty("VERSION") + "\n"
381 + "Jalview Installation: "
382 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
383 + "\n" + "Build Date: "
384 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
385 + "Java version: " + System.getProperty("java.version") + "\n"
386 + System.getProperty("os.arch") + " "
387 + System.getProperty("os.name") + " "
388 + System.getProperty("os.version"));
390 showConsole(showjconsole);
392 showNews.setVisible(false);
394 experimentalFeatures.setSelected(showExperimental());
396 getIdentifiersOrgData();
400 this.addWindowListener(new WindowAdapter()
403 public void windowClosing(WindowEvent evt)
410 this.addMouseListener(ma = new MouseAdapter()
413 public void mousePressed(MouseEvent evt)
415 if (evt.isPopupTrigger()) // Mac
417 showPasteMenu(evt.getX(), evt.getY());
422 public void mouseReleased(MouseEvent evt)
424 if (evt.isPopupTrigger()) // Windows
426 showPasteMenu(evt.getX(), evt.getY());
430 desktop.addMouseListener(ma);
432 this.addFocusListener(new FocusListener()
436 public void focusLost(FocusEvent e)
438 // TODO Auto-generated method stub
443 public void focusGained(FocusEvent e)
445 Cache.log.debug("Relaying windows after focus gain");
446 // make sure that we sort windows properly after we gain focus
447 instance.relayerWindows();
450 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
451 // Spawn a thread that shows the splashscreen
452 SwingUtilities.invokeLater(new Runnable()
461 // Thread off a new instance of the file chooser - this reduces the time it
462 // takes to open it later on.
463 new Thread(new Runnable()
468 Cache.log.debug("Filechooser init thread started.");
469 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
470 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
472 Cache.log.debug("Filechooser init thread finished.");
475 // Add the service change listener
476 changeSupport.addJalviewPropertyChangeListener("services",
477 new PropertyChangeListener()
481 public void propertyChange(PropertyChangeEvent evt)
483 Cache.log.debug("Firing service changed event for "
484 + evt.getNewValue());
485 JalviewServicesChanged(evt);
492 * Answers true if user preferences to enable experimental features is True
497 public boolean showExperimental()
499 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
500 Boolean.FALSE.toString());
501 return Boolean.valueOf(experimental).booleanValue();
504 public void doConfigureStructurePrefs()
506 // configure services
507 StructureSelectionManager ssm = StructureSelectionManager
508 .getStructureSelectionManager(this);
509 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
511 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
512 Preferences.ADD_TEMPFACT_ANN, true));
513 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
514 Preferences.STRUCT_FROM_PDB, true));
515 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
516 Preferences.USE_RNAVIEW, true));
520 ssm.setAddTempFacAnnot(false);
521 ssm.setProcessSecondaryStructure(false);
522 ssm.setSecStructServices(false);
526 public void checkForNews()
528 final Desktop me = this;
529 // Thread off the news reader, in case there are connection problems.
530 addDialogThread(new Runnable()
535 Cache.log.debug("Starting news thread.");
537 jvnews = new BlogReader(me);
538 showNews.setVisible(true);
539 Cache.log.debug("Completed news thread.");
544 public void getIdentifiersOrgData()
546 // Thread off the identifiers fetcher
547 addDialogThread(new Runnable()
552 Cache.log.debug("Downloading data from identifiers.org");
553 UrlDownloadClient client = new UrlDownloadClient();
556 client.download(IdOrgSettings.getUrl(),
557 IdOrgSettings.getDownloadLocation());
558 } catch (IOException e)
560 Cache.log.debug("Exception downloading identifiers.org data"
568 protected void showNews_actionPerformed(ActionEvent e)
570 showNews(showNews.isSelected());
573 void showNews(boolean visible)
576 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
577 showNews.setSelected(visible);
578 if (visible && !jvnews.isVisible())
580 new Thread(new Runnable()
585 long now = System.currentTimeMillis();
586 Desktop.instance.setProgressBar(
587 MessageManager.getString("status.refreshing_news"), now);
588 jvnews.refreshNews();
589 Desktop.instance.setProgressBar(null, now);
598 * recover the last known dimensions for a jalview window
601 * - empty string is desktop, all other windows have unique prefix
602 * @return null or last known dimensions scaled to current geometry (if last
603 * window geom was known)
605 Rectangle getLastKnownDimensions(String windowName)
607 // TODO: lock aspect ratio for scaling desktop Bug #0058199
608 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
609 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
610 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
611 String width = jalview.bin.Cache.getProperty(windowName
613 String height = jalview.bin.Cache.getProperty(windowName
615 if ((x != null) && (y != null) && (width != null) && (height != null))
617 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
618 .parseInt(width), ih = Integer.parseInt(height);
619 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
621 // attempt #1 - try to cope with change in screen geometry - this
622 // version doesn't preserve original jv aspect ratio.
623 // take ratio of current screen size vs original screen size.
624 double sw = ((1f * screenSize.width) / (1f * Integer
625 .parseInt(jalview.bin.Cache
626 .getProperty("SCREENGEOMETRY_WIDTH"))));
627 double sh = ((1f * screenSize.height) / (1f * Integer
628 .parseInt(jalview.bin.Cache
629 .getProperty("SCREENGEOMETRY_HEIGHT"))));
630 // rescale the bounds depending upon the current screen geometry.
631 ix = (int) (ix * sw);
632 iw = (int) (iw * sw);
633 iy = (int) (iy * sh);
634 ih = (int) (ih * sh);
635 while (ix >= screenSize.width)
637 jalview.bin.Cache.log
638 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
639 ix -= screenSize.width;
641 while (iy >= screenSize.height)
643 jalview.bin.Cache.log
644 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
645 iy -= screenSize.height;
647 jalview.bin.Cache.log.debug("Got last known dimensions for "
648 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
651 // return dimensions for new instance
652 return new Rectangle(ix, iy, iw, ih);
657 private void doVamsasClientCheck()
659 if (jalview.bin.Cache.vamsasJarsPresent())
661 setupVamsasDisconnectedGui();
662 VamsasMenu.setVisible(true);
663 final Desktop us = this;
664 VamsasMenu.addMenuListener(new MenuListener()
666 // this listener remembers when the menu was first selected, and
667 // doesn't rebuild the session list until it has been cleared and
669 boolean refresh = true;
672 public void menuCanceled(MenuEvent e)
678 public void menuDeselected(MenuEvent e)
684 public void menuSelected(MenuEvent e)
688 us.buildVamsasStMenu();
693 vamsasStart.setVisible(true);
697 void showPasteMenu(int x, int y)
699 JPopupMenu popup = new JPopupMenu();
700 JMenuItem item = new JMenuItem(
701 MessageManager.getString("label.paste_new_window"));
702 item.addActionListener(new ActionListener()
705 public void actionPerformed(ActionEvent evt)
712 popup.show(this, x, y);
719 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
720 Transferable contents = c.getContents(this);
722 if (contents != null)
724 String file = (String) contents
725 .getTransferData(DataFlavor.stringFlavor);
727 FileFormatI format = new IdentifyFile().identify(file,
728 DataSourceType.PASTE);
730 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
733 } catch (Exception ex)
736 .println("Unable to paste alignment from system clipboard:\n"
742 * Adds and opens the given frame to the desktop
753 public static synchronized void addInternalFrame(
754 final JInternalFrame frame, String title, int w, int h)
756 addInternalFrame(frame, title, true, w, h, true, false);
760 * Add an internal frame to the Jalview desktop
767 * When true, display frame immediately, otherwise, caller must call
768 * setVisible themselves.
774 public static synchronized void addInternalFrame(
775 final JInternalFrame frame, String title, boolean makeVisible,
778 addInternalFrame(frame, title, makeVisible, w, h, true, false);
782 * Add an internal frame to the Jalview desktop and make it visible
795 public static synchronized void addInternalFrame(
796 final JInternalFrame frame, String title, int w, int h,
799 addInternalFrame(frame, title, true, w, h, resizable, false);
803 * Add an internal frame to the Jalview desktop
810 * When true, display frame immediately, otherwise, caller must call
811 * setVisible themselves.
818 * @param ignoreMinSize
819 * Do not set the default minimum size for frame
821 public static synchronized void addInternalFrame(
822 final JInternalFrame frame, String title, boolean makeVisible,
823 int w, int h, boolean resizable, boolean ignoreMinSize)
826 // TODO: allow callers to determine X and Y position of frame (eg. via
828 // TODO: consider fixing method to update entries in the window submenu with
829 // the current window title
831 frame.setTitle(title);
832 if (frame.getWidth() < 1 || frame.getHeight() < 1)
836 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
837 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
838 // IF JALVIEW IS RUNNING HEADLESS
839 // ///////////////////////////////////////////////
841 || (System.getProperty("java.awt.headless") != null && System
842 .getProperty("java.awt.headless").equals("true")))
851 frame.setMinimumSize(new Dimension(DEFAULT_MIN_WIDTH,
852 DEFAULT_MIN_HEIGHT));
854 // Set default dimension for Alignment Frame window.
855 // The Alignment Frame window could be added from a number of places,
857 // I did this here in order not to miss out on any Alignment frame.
858 if (frame instanceof AlignFrame)
860 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
861 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);
871 if (Platform.isAMac())
873 frame.setIconifiable(false);
874 frame.setFrameIcon(null);
875 // frame.setDesktopIcon(null);
876 frame.setDoubleBuffered(false);
878 if (frame.getX() < 1 && frame.getY() < 1)
880 frame.setLocation(xOffset * openFrameCount, yOffset
881 * ((openFrameCount - 1) % 10) + yOffset);
885 * add an entry for the new frame in the Window menu
886 * (and remove it when the frame is closed)
888 final JMenuItem menuItem = new JMenuItem(title);
889 frame.addInternalFrameListener(new InternalFrameAdapter()
892 public void internalFrameActivated(InternalFrameEvent evt)
894 JInternalFrame itf = desktop.getSelectedFrame();
902 public void internalFrameClosed(InternalFrameEvent evt)
904 PaintRefresher.RemoveComponent(frame);
907 * defensive check to prevent frames being
908 * added half off the window
910 if (openFrameCount > 0)
916 * ensure no reference to alignFrame retained by menu item listener
918 if (menuItem.getActionListeners().length > 0)
920 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
922 windowMenu.remove(menuItem);
923 JInternalFrame itf = desktop.getSelectedFrame();
927 if (itf instanceof AlignFrame)
929 Jalview.setCurrentAlignFrame((AlignFrame) itf);
936 menuItem.addActionListener(new ActionListener()
939 public void actionPerformed(ActionEvent e)
943 frame.setSelected(true);
944 frame.setIcon(false);
945 } catch (java.beans.PropertyVetoException ex)
954 windowMenu.add(menuItem);
959 frame.setSelected(true);
960 frame.requestFocus();
961 } catch (java.beans.PropertyVetoException ve)
963 } catch (java.lang.ClassCastException cex)
966 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
972 public void lostOwnership(Clipboard clipboard, Transferable contents)
976 Desktop.jalviewClipboard = null;
979 internalCopy = false;
983 public void dragEnter(DropTargetDragEvent evt)
988 public void dragExit(DropTargetEvent evt)
993 public void dragOver(DropTargetDragEvent evt)
998 public void dropActionChanged(DropTargetDragEvent evt)
1009 public void drop(DropTargetDropEvent evt)
1011 boolean success = true;
1012 // JAL-1552 - acceptDrop required before getTransferable call for
1013 // Java's Transferable for native dnd
1014 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1015 Transferable t = evt.getTransferable();
1016 List<String> files = new ArrayList<String>();
1017 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
1021 Desktop.transferFromDropTarget(files, protocols, evt, t);
1022 } catch (Exception e)
1024 e.printStackTrace();
1032 for (int i = 0; i < files.size(); i++)
1034 String file = files.get(i).toString();
1035 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1037 FileFormatI format = null;
1039 if (file.endsWith(".jar"))
1041 format = FileFormat.Jalview;
1046 format = new IdentifyFile().identify(file, protocol);
1049 new FileLoader().LoadFile(file, protocol, format);
1052 } catch (Exception ex)
1057 evt.dropComplete(success); // need this to ensure input focus is properly
1058 // transfered to any new windows created
1068 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1070 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1071 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1072 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1074 chooser.setFileView(new JalviewFileView());
1075 chooser.setDialogTitle(MessageManager
1076 .getString("label.open_local_file"));
1077 chooser.setToolTipText(MessageManager.getString("action.open"));
1079 int value = chooser.showOpenDialog(this);
1081 if (value == JalviewFileChooser.APPROVE_OPTION)
1083 String choice = chooser.getSelectedFile().getPath();
1084 Cache.setProperty("LAST_DIRECTORY", chooser
1085 .getSelectedFile().getParent());
1087 FileFormatI format = chooser.getSelectedFormat();
1090 * Call IdentifyFile to verify the file contains what its extension implies.
1091 * Skip this step for dynamically added file formats, because
1092 * IdentifyFile does not know how to recognise them.
1094 if (FileFormats.getInstance().isIdentifiable(format))
1098 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1099 } catch (FileFormatException e)
1101 // format = null; //??
1105 if (viewport != null)
1107 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1112 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1124 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1126 // This construct allows us to have a wider textfield
1128 JLabel label = new JLabel(
1129 MessageManager.getString("label.input_file_url"));
1130 final JComboBox history = new JComboBox();
1132 JPanel panel = new JPanel(new GridLayout(2, 1));
1135 history.setPreferredSize(new Dimension(400, 20));
1136 history.setEditable(true);
1137 history.addItem("http://www.");
1139 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1143 if (historyItems != null)
1145 st = new StringTokenizer(historyItems, "\t");
1147 while (st.hasMoreTokens())
1149 history.addItem(st.nextElement());
1153 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1154 MessageManager.getString("label.input_alignment_from_url"),
1155 JvOptionPane.OK_CANCEL_OPTION);
1157 if (reply != JvOptionPane.OK_OPTION)
1162 String url = history.getSelectedItem().toString();
1164 if (url.toLowerCase().endsWith(".jar"))
1166 if (viewport != null)
1168 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1169 FileFormat.Jalview);
1173 new FileLoader().LoadFile(url, DataSourceType.URL,
1174 FileFormat.Jalview);
1179 FileFormatI format = null;
1182 format = new IdentifyFile().identify(url, DataSourceType.URL);
1183 } catch (FileFormatException e)
1185 // TODO revise error handling, distinguish between
1186 // URL not found and response not valid
1191 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1192 MessageManager.formatMessage("label.couldnt_locate",
1193 new Object[] { url }), MessageManager
1194 .getString("label.url_not_found"),
1195 JvOptionPane.WARNING_MESSAGE);
1200 if (viewport != null)
1203 .LoadFile(viewport, url, DataSourceType.URL, format);
1207 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1213 * Opens the CutAndPaste window for the user to paste an alignment in to
1216 * - if not null, the pasted alignment is added to the current
1217 * alignment; if null, to a new alignment window
1220 public void inputTextboxMenuItem_actionPerformed(
1221 AlignmentViewPanel viewPanel)
1223 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1224 cap.setForInput(viewPanel);
1225 Desktop.addInternalFrame(cap,
1226 MessageManager.getString("label.cut_paste_alignmen_file"),
1236 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1238 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1239 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1241 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1242 getBounds().y, getWidth(), getHeight()));
1244 if (jconsole != null)
1246 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1247 jconsole.stopConsole();
1251 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1254 if (dialogExecutor != null)
1256 dialogExecutor.shutdownNow();
1258 closeAll_actionPerformed(null);
1260 if (groovyConsole != null)
1262 // suppress a possible repeat prompt to save script
1263 groovyConsole.setDirty(false);
1264 groovyConsole.exit();
1269 private void storeLastKnownDimensions(String string, Rectangle jc)
1271 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1272 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1273 + " height:" + jc.height);
1275 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1276 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1277 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1278 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1288 public void aboutMenuItem_actionPerformed(ActionEvent e)
1290 // StringBuffer message = getAboutMessage(false);
1291 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1293 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1294 new Thread(new Runnable()
1299 new SplashScreen(true);
1304 public StringBuffer getAboutMessage(boolean shortv)
1306 StringBuffer message = new StringBuffer();
1307 message.append("<html>");
1310 message.append("<h1><strong>Version: "
1311 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1312 message.append("<strong>Last Updated: <em>"
1313 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1314 + "</em></strong>");
1320 message.append("<strong>Version "
1321 + jalview.bin.Cache.getProperty("VERSION")
1322 + "; last updated: "
1323 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1326 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1329 message.append("<br>...Checking latest version...</br>");
1331 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1332 .equals(jalview.bin.Cache.getProperty("VERSION")))
1334 boolean red = false;
1335 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1336 .indexOf("automated build") == -1)
1339 // Displayed when code version and jnlp version do not match and code
1340 // version is not a development build
1341 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1344 message.append("<br>!! Version "
1345 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1347 + " is available for download from "
1348 + jalview.bin.Cache.getDefault("www.jalview.org",
1349 "http://www.jalview.org") + " !!");
1352 message.append("</div>");
1355 message.append("<br>Authors: "
1357 .getDefault("AUTHORFNAMES",
1358 "The Jalview Authors (See AUTHORS file for current list)")
1359 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1360 + "<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"
1361 + "<br><br>If you use Jalview, please cite:"
1362 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1363 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1364 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1376 public void documentationMenuItem_actionPerformed(ActionEvent e)
1380 Help.showHelpWindow();
1381 } catch (Exception ex)
1387 public void closeAll_actionPerformed(ActionEvent e)
1389 // TODO show a progress bar while closing?
1390 JInternalFrame[] frames = desktop.getAllFrames();
1391 for (int i = 0; i < frames.length; i++)
1395 frames[i].setClosed(true);
1396 } catch (java.beans.PropertyVetoException ex)
1400 Jalview.setCurrentAlignFrame(null);
1401 System.out.println("ALL CLOSED");
1402 if (v_client != null)
1404 // TODO clear binding to vamsas document objects on close_all
1408 * reset state of singleton objects as appropriate (clear down session state
1409 * when all windows are closed)
1411 StructureSelectionManager ssm = StructureSelectionManager
1412 .getStructureSelectionManager(this);
1421 public void raiseRelated_actionPerformed(ActionEvent e)
1423 reorderAssociatedWindows(false, false);
1427 public void minimizeAssociated_actionPerformed(ActionEvent e)
1429 reorderAssociatedWindows(true, false);
1432 void closeAssociatedWindows()
1434 reorderAssociatedWindows(false, true);
1440 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1444 protected void garbageCollect_actionPerformed(ActionEvent e)
1446 // We simply collect the garbage
1447 jalview.bin.Cache.log.debug("Collecting garbage...");
1449 jalview.bin.Cache.log.debug("Finished garbage collection.");
1456 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1460 protected void showMemusage_actionPerformed(ActionEvent e)
1462 desktop.showMemoryUsage(showMemusage.isSelected());
1469 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1473 protected void showConsole_actionPerformed(ActionEvent e)
1475 showConsole(showConsole.isSelected());
1478 Console jconsole = null;
1481 * control whether the java console is visible or not
1485 void showConsole(boolean selected)
1487 showConsole.setSelected(selected);
1488 // TODO: decide if we should update properties file
1489 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1491 jconsole.setVisible(selected);
1494 void reorderAssociatedWindows(boolean minimize, boolean close)
1496 JInternalFrame[] frames = desktop.getAllFrames();
1497 if (frames == null || frames.length < 1)
1502 AlignmentViewport source = null, target = null;
1503 if (frames[0] instanceof AlignFrame)
1505 source = ((AlignFrame) frames[0]).getCurrentView();
1507 else if (frames[0] instanceof TreePanel)
1509 source = ((TreePanel) frames[0]).getViewPort();
1511 else if (frames[0] instanceof PCAPanel)
1513 source = ((PCAPanel) frames[0]).av;
1515 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1517 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1522 for (int i = 0; i < frames.length; i++)
1525 if (frames[i] == null)
1529 if (frames[i] instanceof AlignFrame)
1531 target = ((AlignFrame) frames[i]).getCurrentView();
1533 else if (frames[i] instanceof TreePanel)
1535 target = ((TreePanel) frames[i]).getViewPort();
1537 else if (frames[i] instanceof PCAPanel)
1539 target = ((PCAPanel) frames[i]).av;
1541 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1543 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1546 if (source == target)
1552 frames[i].setClosed(true);
1556 frames[i].setIcon(minimize);
1559 frames[i].toFront();
1563 } catch (java.beans.PropertyVetoException ex)
1578 protected void preferences_actionPerformed(ActionEvent e)
1590 public void saveState_actionPerformed(ActionEvent e)
1592 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1595 chooser.setFileView(new JalviewFileView());
1596 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1598 int value = chooser.showSaveDialog(this);
1600 if (value == JalviewFileChooser.APPROVE_OPTION)
1602 final Desktop me = this;
1603 final java.io.File choice = chooser.getSelectedFile();
1604 setProjectFile(choice);
1606 new Thread(new Runnable()
1611 // TODO: refactor to Jalview desktop session controller action.
1612 setProgressBar(MessageManager.formatMessage(
1613 "label.saving_jalview_project",
1614 new Object[] { choice.getName() }), choice.hashCode());
1615 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1616 choice.getParent());
1617 // TODO catch and handle errors for savestate
1618 // TODO prevent user from messing with the Desktop whilst we're saving
1621 new Jalview2XML().saveState(choice);
1622 } catch (OutOfMemoryError oom)
1624 new OOMWarning("Whilst saving current state to "
1625 + choice.getName(), oom);
1626 } catch (Exception ex)
1629 "Problems whilst trying to save to " + choice.getName(),
1631 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1632 "label.error_whilst_saving_current_state_to",
1633 new Object[] { choice.getName() }), MessageManager
1634 .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[] {
1664 "jvp", "jar" }, new String[] { "Jalview Project",
1665 "Jalview Project (old)" }, "Jalview Project");
1666 chooser.setFileView(new JalviewFileView());
1667 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1669 int value = chooser.showOpenDialog(this);
1671 if (value == JalviewFileChooser.APPROVE_OPTION)
1673 final File selectedFile = chooser.getSelectedFile();
1674 setProjectFile(selectedFile);
1675 final String choice = selectedFile.getAbsolutePath();
1676 Cache.setProperty("LAST_DIRECTORY",
1677 selectedFile.getParent());
1678 new Thread(new Runnable()
1684 MessageManager.formatMessage(
1685 "label.loading_jalview_project",
1686 new Object[] { 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)
1695 Cache.log.error("Problems whilst loading project from "
1697 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1699 "label.error_whilst_loading_project_from",
1700 new Object[] { choice }), MessageManager
1701 .getString("label.couldnt_load_project"),
1702 JvOptionPane.WARNING_MESSAGE);
1704 setProgressBar(null, choice.hashCode());
1711 public void inputSequence_actionPerformed(ActionEvent e)
1713 new SequenceFetcher(this);
1716 JPanel progressPanel;
1718 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1720 public void startLoading(final String fileName)
1722 if (fileLoadingCount == 0)
1724 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1725 "label.loading_file", new Object[] { fileName })));
1730 private JPanel addProgressPanel(String string)
1732 if (progressPanel == null)
1734 progressPanel = new JPanel(new GridLayout(1, 1));
1735 totalProgressCount = 0;
1736 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1738 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1739 JProgressBar progressBar = new JProgressBar();
1740 progressBar.setIndeterminate(true);
1742 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1744 thisprogress.add(progressBar, BorderLayout.CENTER);
1745 progressPanel.add(thisprogress);
1746 ((GridLayout) progressPanel.getLayout())
1747 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1748 ++totalProgressCount;
1749 instance.validate();
1750 return thisprogress;
1753 int totalProgressCount = 0;
1755 private void removeProgressPanel(JPanel progbar)
1757 if (progressPanel != null)
1759 synchronized (progressPanel)
1761 progressPanel.remove(progbar);
1762 GridLayout gl = (GridLayout) progressPanel.getLayout();
1763 gl.setRows(gl.getRows() - 1);
1764 if (--totalProgressCount < 1)
1766 this.getContentPane().remove(progressPanel);
1767 progressPanel = null;
1774 public void stopLoading()
1777 if (fileLoadingCount < 1)
1779 while (fileLoadingPanels.size() > 0)
1781 removeProgressPanel(fileLoadingPanels.remove(0));
1783 fileLoadingPanels.clear();
1784 fileLoadingCount = 0;
1789 public static int getViewCount(String alignmentId)
1791 AlignmentViewport[] aps = getViewports(alignmentId);
1792 return (aps == null) ? 0 : aps.length;
1797 * @param alignmentId
1798 * - if null, all sets are returned
1799 * @return all AlignmentPanels concerning the alignmentId sequence set
1801 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1803 if (Desktop.desktop == null)
1805 // no frames created and in headless mode
1806 // TODO: verify that frames are recoverable when in headless mode
1809 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1810 AlignFrame[] frames = getAlignFrames();
1815 for (AlignFrame af : frames)
1817 for (AlignmentPanel ap : af.alignPanels)
1819 if (alignmentId == null
1820 || alignmentId.equals(ap.av.getSequenceSetId()))
1826 if (aps.size() == 0)
1830 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1835 * get all the viewports on an alignment.
1837 * @param sequenceSetId
1838 * unique alignment id (may be null - all viewports returned in that
1840 * @return all viewports on the alignment bound to sequenceSetId
1842 public static AlignmentViewport[] getViewports(String sequenceSetId)
1844 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1845 if (desktop != null)
1847 AlignFrame[] frames = Desktop.getAlignFrames();
1849 for (AlignFrame afr : frames)
1851 if (sequenceSetId == null
1852 || afr.getViewport().getSequenceSetId()
1853 .equals(sequenceSetId))
1855 if (afr.alignPanels != null)
1857 for (AlignmentPanel ap : afr.alignPanels)
1859 if (sequenceSetId == null
1860 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1868 viewp.add(afr.getViewport());
1872 if (viewp.size() > 0)
1874 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1881 * Explode the views in the given frame into separate AlignFrame
1885 public static void explodeViews(AlignFrame af)
1887 int size = af.alignPanels.size();
1893 for (int i = 0; i < size; i++)
1895 AlignmentPanel ap = af.alignPanels.get(i);
1896 AlignFrame newaf = new AlignFrame(ap);
1899 * Restore the view's last exploded frame geometry if known. Multiple
1900 * views from one exploded frame share and restore the same (frame)
1901 * position and size.
1903 Rectangle geometry = ap.av.getExplodedGeometry();
1904 if (geometry != null)
1906 newaf.setBounds(geometry);
1909 ap.av.setGatherViewsHere(false);
1911 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1912 AlignFrame.DEFAULT_HEIGHT);
1915 af.alignPanels.clear();
1916 af.closeMenuItem_actionPerformed(true);
1921 * Gather expanded views (separate AlignFrame's) with the same sequence set
1922 * identifier back in to this frame as additional views, and close the
1923 * expanded views. Note the expanded frames may themselves have multiple
1924 * views. We take the lot.
1928 public void gatherViews(AlignFrame source)
1930 source.viewport.setGatherViewsHere(true);
1931 source.viewport.setExplodedGeometry(source.getBounds());
1932 JInternalFrame[] frames = desktop.getAllFrames();
1933 String viewId = source.viewport.getSequenceSetId();
1935 for (int t = 0; t < frames.length; t++)
1937 if (frames[t] instanceof AlignFrame && frames[t] != source)
1939 AlignFrame af = (AlignFrame) frames[t];
1940 boolean gatherThis = false;
1941 for (int a = 0; a < af.alignPanels.size(); a++)
1943 AlignmentPanel ap = af.alignPanels.get(a);
1944 if (viewId.equals(ap.av.getSequenceSetId()))
1947 ap.av.setGatherViewsHere(false);
1948 ap.av.setExplodedGeometry(af.getBounds());
1949 source.addAlignmentPanel(ap, false);
1955 af.alignPanels.clear();
1956 af.closeMenuItem_actionPerformed(true);
1963 jalview.gui.VamsasApplication v_client = null;
1966 public void vamsasImport_actionPerformed(ActionEvent e)
1968 if (v_client == null)
1970 // Load and try to start a session.
1971 JalviewFileChooser chooser = new JalviewFileChooser(
1972 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1974 chooser.setFileView(new JalviewFileView());
1975 chooser.setDialogTitle(MessageManager
1976 .getString("label.open_saved_vamsas_session"));
1977 chooser.setToolTipText(MessageManager
1978 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1980 int value = chooser.showOpenDialog(this);
1982 if (value == JalviewFileChooser.APPROVE_OPTION)
1984 String fle = chooser.getSelectedFile().toString();
1985 if (!vamsasImport(chooser.getSelectedFile()))
1988 .showInternalMessageDialog(
1990 MessageManager.formatMessage(
1991 "label.couldnt_import_as_vamsas_session",
1992 new Object[] { fle }),
1994 .getString("label.vamsas_document_import_failed"),
1995 JvOptionPane.ERROR_MESSAGE);
2001 jalview.bin.Cache.log
2002 .error("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
2019 .error("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 "
2047 setupVamsasConnectedGui();
2048 v_client.initial_update(); // TODO: thread ?
2049 return v_client.inSession();
2053 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2056 * @return true if import was a success and a session was started.
2058 public boolean vamsasImport(File file)
2060 if (v_client != null)
2063 jalview.bin.Cache.log
2064 .error("Implementation error - load session from a running session is not supported.");
2068 setProgressBar(MessageManager.formatMessage(
2069 "status.importing_vamsas_session_from",
2070 new Object[] { file.getName() }), file.hashCode());
2073 v_client = new jalview.gui.VamsasApplication(this, file, null);
2074 } catch (Exception ex)
2076 setProgressBar(MessageManager.formatMessage(
2077 "status.importing_vamsas_session_from",
2078 new Object[] { file.getName() }), file.hashCode());
2079 jalview.bin.Cache.log.error(
2080 "New vamsas session from existing session file failed:", ex);
2083 setupVamsasConnectedGui();
2084 v_client.initial_update(); // TODO: thread ?
2085 setProgressBar(MessageManager.formatMessage(
2086 "status.importing_vamsas_session_from",
2087 new Object[] { file.getName() }), file.hashCode());
2088 return v_client.inSession();
2091 public boolean joinVamsasSession(String mysesid)
2093 if (v_client != null)
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);
2155 vamsasStart.setText(MessageManager
2156 .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(
2181 "Problem getting current sessions list.", e);
2186 jalview.bin.Cache.log.debug("Got current sessions list: "
2187 + 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.formatMessage(
2194 "label.connect_to_session", new Object[] { sess[i] }));
2195 final Desktop dsktp = this;
2196 final String mysesid = sess[i];
2197 sessit.addActionListener(new ActionListener()
2201 public void actionPerformed(ActionEvent e)
2203 if (dsktp.v_client == null)
2205 Thread rthr = new Thread(new Runnable()
2211 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2212 dsktp.setupVamsasConnectedGui();
2213 dsktp.v_client.initial_update();
2221 VamsasStMenu.add(sessit);
2223 // don't show an empty menu.
2224 VamsasStMenu.setVisible(sess.length > 0);
2229 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2230 VamsasStMenu.removeAll();
2231 VamsasStMenu.setVisible(false);
2236 // Not interested in the content. Just hide ourselves.
2237 VamsasStMenu.setVisible(false);
2242 public void vamsasSave_actionPerformed(ActionEvent e)
2244 if (v_client != null)
2246 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2247 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2250 chooser.setFileView(new JalviewFileView());
2251 chooser.setDialogTitle(MessageManager
2252 .getString("label.save_vamsas_document_archive"));
2254 int value = chooser.showSaveDialog(this);
2256 if (value == JalviewFileChooser.APPROVE_OPTION)
2258 java.io.File choice = chooser.getSelectedFile();
2259 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2260 "label.saving_vamsas_doc",
2261 new Object[] { choice.getName() }));
2262 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2263 String warnmsg = null;
2264 String warnttl = null;
2267 v_client.vclient.storeDocument(choice);
2270 warnttl = "Serious Problem saving Vamsas Document";
2271 warnmsg = ex.toString();
2272 jalview.bin.Cache.log.error("Error Whilst saving document to "
2275 } catch (Exception ex)
2277 warnttl = "Problem saving Vamsas Document.";
2278 warnmsg = ex.toString();
2279 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2283 removeProgressPanel(progpanel);
2284 if (warnmsg != null)
2286 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2288 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2294 JPanel vamUpdate = null;
2297 * hide vamsas user gui bits when a vamsas document event is being handled.
2300 * true to hide gui, false to reveal gui
2302 public void setVamsasUpdate(boolean b)
2304 Cache.log.debug("Setting gui for Vamsas update "
2305 + (b ? "in progress" : "finished"));
2307 if (vamUpdate != null)
2309 this.removeProgressPanel(vamUpdate);
2313 vamUpdate = this.addProgressPanel(MessageManager
2314 .getString("label.updating_vamsas_session"));
2316 vamsasStart.setVisible(!b);
2317 vamsasStop.setVisible(!b);
2318 vamsasSave.setVisible(!b);
2321 public JInternalFrame[] getAllFrames()
2323 return desktop.getAllFrames();
2327 * Checks the given url to see if it gives a response indicating that the user
2328 * should be informed of a new questionnaire.
2332 public void checkForQuestionnaire(String url)
2334 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2335 // javax.swing.SwingUtilities.invokeLater(jvq);
2336 new Thread(jvq).start();
2339 public void checkURLLinks()
2341 // Thread off the URL link checker
2342 addDialogThread(new Runnable()
2347 if (Cache.getDefault("CHECKURLLINKS", true))
2349 // check what the actual links are - if it's just the default don't
2350 // bother with the warning
2351 List<String> links = Preferences.sequenceUrlLinks
2354 // only need to check links if there is one with a
2355 // SEQUENCE_ID which is not the default EMBL_EBI link
2356 ListIterator<String> li = links.listIterator();
2357 boolean check = false;
2358 List<JLabel> urls = new ArrayList<JLabel>();
2359 while (li.hasNext())
2361 String link = li.next();
2362 if (link.contains(SEQUENCE_ID)
2363 && !link.equals(UrlConstants.DEFAULT_STRING))
2366 int barPos = link.indexOf("|");
2367 String urlMsg = barPos == -1 ? link : link.substring(0,
2368 barPos) + ": " + link.substring(barPos + 1);
2369 urls.add(new JLabel(urlMsg));
2377 // ask user to check in case URL links use old style tokens
2378 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2379 JPanel msgPanel = new JPanel();
2380 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2381 msgPanel.add(Box.createVerticalGlue());
2382 JLabel msg = new JLabel(
2384 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2385 JLabel msg2 = new JLabel(
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);
2455 public boolean isShowMemoryUsage()
2457 return showMemoryUsage;
2463 df = java.text.NumberFormat.getNumberInstance();
2464 df.setMaximumFractionDigits(2);
2465 runtime = Runtime.getRuntime();
2467 while (showMemoryUsage)
2471 maxMemory = runtime.maxMemory() / ONE_MB;
2472 allocatedMemory = runtime.totalMemory() / ONE_MB;
2473 freeMemory = runtime.freeMemory() / ONE_MB;
2474 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2476 percentUsage = (totalFreeMemory / maxMemory) * 100;
2478 // if (percentUsage < 20)
2480 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2482 // instance.set.setBorder(border1);
2485 // sleep after showing usage
2487 } catch (Exception ex)
2489 ex.printStackTrace();
2495 public void paintComponent(Graphics g)
2497 if (showMemoryUsage && g != null && df != null)
2499 if (percentUsage < 20)
2501 g.setColor(Color.red);
2503 FontMetrics fm = g.getFontMetrics();
2506 g.drawString(MessageManager.formatMessage(
2507 "label.memory_stats",
2508 new Object[] { df.format(totalFreeMemory),
2509 df.format(maxMemory), df.format(percentUsage) }), 10,
2510 getHeight() - fm.getHeight());
2517 * fixes stacking order after a modal dialog to ensure windows that should be
2518 * on top actually are
2520 public void relayerWindows()
2526 * Accessor method to quickly get all the AlignmentFrames loaded.
2528 * @return an array of AlignFrame, or null if none found
2530 public static AlignFrame[] getAlignFrames()
2532 if (Jalview.isHeadlessMode())
2534 // Desktop.desktop is null in headless mode
2535 return new AlignFrame[] { Jalview.currentAlignFrame };
2538 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2544 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2546 for (int i = frames.length - 1; i > -1; i--)
2548 if (frames[i] instanceof AlignFrame)
2550 avp.add((AlignFrame) frames[i]);
2552 else if (frames[i] instanceof SplitFrame)
2555 * Also check for a split frame containing an AlignFrame
2557 GSplitFrame sf = (GSplitFrame) frames[i];
2558 if (sf.getTopFrame() instanceof AlignFrame)
2560 avp.add((AlignFrame) sf.getTopFrame());
2562 if (sf.getBottomFrame() instanceof AlignFrame)
2564 avp.add((AlignFrame) sf.getBottomFrame());
2568 if (avp.size() == 0)
2572 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2577 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2581 public GStructureViewer[] getJmols()
2583 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2589 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2591 for (int i = frames.length - 1; i > -1; i--)
2593 if (frames[i] instanceof AppJmol)
2595 GStructureViewer af = (GStructureViewer) frames[i];
2599 if (avp.size() == 0)
2603 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2608 * Add Groovy Support to Jalview
2611 public void groovyShell_actionPerformed()
2615 openGroovyConsole();
2616 } catch (Exception ex)
2618 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2619 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2621 MessageManager.getString("label.couldnt_create_groovy_shell"),
2622 MessageManager.getString("label.groovy_support_failed"),
2623 JvOptionPane.ERROR_MESSAGE);
2628 * Open the Groovy console
2630 void openGroovyConsole()
2632 if (groovyConsole == null)
2634 groovyConsole = new groovy.ui.Console();
2635 groovyConsole.setVariable("Jalview", this);
2636 groovyConsole.run();
2639 * We allow only one console at a time, so that AlignFrame menu option
2640 * 'Calculate | Run Groovy script' is unambiguous.
2641 * Disable 'Groovy Console', and enable 'Run script', when the console is
2642 * opened, and the reverse when it is closed
2644 Window window = (Window) groovyConsole.getFrame();
2645 window.addWindowListener(new WindowAdapter()
2648 public void windowClosed(WindowEvent e)
2651 * rebind CMD-Q from Groovy Console to Jalview Quit
2654 enableExecuteGroovy(false);
2660 * show Groovy console window (after close and reopen)
2662 ((Window) groovyConsole.getFrame()).setVisible(true);
2665 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2666 * and disable opening a second console
2668 enableExecuteGroovy(true);
2672 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2673 * binding when opened
2675 protected void addQuitHandler()
2677 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2678 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2679 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2680 getRootPane().getActionMap().put("Quit", new AbstractAction()
2683 public void actionPerformed(ActionEvent e)
2691 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2694 * true if Groovy console is open
2696 public void enableExecuteGroovy(boolean enabled)
2699 * disable opening a second Groovy console
2700 * (or re-enable when the console is closed)
2702 groovyShell.setEnabled(!enabled);
2704 AlignFrame[] alignFrames = getAlignFrames();
2705 if (alignFrames != null)
2707 for (AlignFrame af : alignFrames)
2709 af.setGroovyEnabled(enabled);
2715 * Progress bars managed by the IProgressIndicator method.
2717 private Hashtable<Long, JPanel> progressBars;
2719 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2724 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2727 public void setProgressBar(String message, long id)
2729 if (progressBars == null)
2731 progressBars = new Hashtable<Long, JPanel>();
2732 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2735 if (progressBars.get(new Long(id)) != null)
2737 JPanel panel = progressBars.remove(new Long(id));
2738 if (progressBarHandlers.contains(new Long(id)))
2740 progressBarHandlers.remove(new Long(id));
2742 removeProgressPanel(panel);
2746 progressBars.put(new Long(id), addProgressPanel(message));
2753 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2754 * jalview.gui.IProgressIndicatorHandler)
2757 public void registerHandler(final long id,
2758 final IProgressIndicatorHandler handler)
2760 if (progressBarHandlers == null
2761 || !progressBars.containsKey(new Long(id)))
2765 .getString("error.call_setprogressbar_before_registering_handler"));
2767 progressBarHandlers.put(new Long(id), handler);
2768 final JPanel progressPanel = progressBars.get(new Long(id));
2769 if (handler.canCancel())
2771 JButton cancel = new JButton(
2772 MessageManager.getString("action.cancel"));
2773 final IProgressIndicator us = this;
2774 cancel.addActionListener(new ActionListener()
2778 public void actionPerformed(ActionEvent e)
2780 handler.cancelActivity(id);
2781 us.setProgressBar(MessageManager.formatMessage(
2782 "label.cancelled_params",
2783 new Object[] { ((JLabel) progressPanel.getComponent(0))
2787 progressPanel.add(cancel, BorderLayout.EAST);
2793 * @return true if any progress bars are still active
2796 public boolean operationInProgress()
2798 if (progressBars != null && progressBars.size() > 0)
2806 * This will return the first AlignFrame holding the given viewport instance.
2807 * It will break if there are more than one AlignFrames viewing a particular
2811 * @return alignFrame for viewport
2813 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2815 if (desktop != null)
2817 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2818 for (int panel = 0; aps != null && panel < aps.length; panel++)
2820 if (aps[panel] != null && aps[panel].av == viewport)
2822 return aps[panel].alignFrame;
2829 public VamsasApplication getVamsasApplication()
2836 * flag set if jalview GUI is being operated programmatically
2838 private boolean inBatchMode = false;
2841 * check if jalview GUI is being operated programmatically
2843 * @return inBatchMode
2845 public boolean isInBatchMode()
2851 * set flag if jalview GUI is being operated programmatically
2853 * @param inBatchMode
2855 public void setInBatchMode(boolean inBatchMode)
2857 this.inBatchMode = inBatchMode;
2860 public void startServiceDiscovery()
2862 startServiceDiscovery(false);
2865 public void startServiceDiscovery(boolean blocking)
2867 boolean alive = true;
2868 Thread t0 = null, t1 = null, t2 = null;
2869 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2872 // todo: changesupport handlers need to be transferred
2873 if (discoverer == null)
2875 discoverer = new jalview.ws.jws1.Discoverer();
2876 // register PCS handler for desktop.
2877 discoverer.addPropertyChangeListener(changeSupport);
2879 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2880 // until we phase out completely
2881 (t0 = new Thread(discoverer)).start();
2884 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2886 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2891 // TODO: do rest service discovery
2900 } catch (Exception e)
2903 alive = (t1 != null && t1.isAlive())
2904 || (t2 != null && t2.isAlive())
2905 || (t3 != null && t3.isAlive())
2906 || (t0 != null && t0.isAlive());
2912 * called to check if the service discovery process completed successfully.
2916 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2918 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2920 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2921 .getErrorMessages();
2924 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2926 if (serviceChangedDialog == null)
2928 // only run if we aren't already displaying one of these.
2929 addDialogThread(serviceChangedDialog = new Runnable()
2936 * JalviewDialog jd =new JalviewDialog() {
2938 * @Override protected void cancelPressed() { // TODO
2939 * Auto-generated method stub
2941 * }@Override protected void okPressed() { // TODO
2942 * Auto-generated method stub
2944 * }@Override protected void raiseClosed() { // TODO
2945 * Auto-generated method stub
2947 * } }; jd.initDialogFrame(new
2948 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2949 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2950 * + " or mis-configured HTTP proxy settings.<br/>" +
2951 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2953 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2954 * ), true, true, "Web Service Configuration Problem", 450,
2957 * jd.waitForInput();
2963 "<html><table width=\"450\"><tr><td>"
2965 + "</td></tr></table>"
2966 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2967 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2968 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2969 + " Tools->Preferences dialog box to change them.</p></html>"),
2970 "Web Service Configuration Problem",
2971 JvOptionPane.DEFAULT_OPTION,
2972 JvOptionPane.ERROR_MESSAGE);
2973 serviceChangedDialog = null;
2982 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2989 private Runnable serviceChangedDialog = null;
2992 * start a thread to open a URL in the configured browser. Pops up a warning
2993 * dialog to the user if there is an exception when calling out to the browser
2998 public static void showUrl(final String url)
3000 showUrl(url, Desktop.instance);
3004 * Like showUrl but allows progress handler to be specified
3008 * (null) or object implementing IProgressIndicator
3010 public static void showUrl(final String url,
3011 final IProgressIndicator progress)
3013 new Thread(new Runnable()
3020 if (progress != null)
3022 progress.setProgressBar(MessageManager.formatMessage(
3023 "status.opening_params", new Object[] { url }), this
3026 jalview.util.BrowserLauncher.openURL(url);
3027 } catch (Exception ex)
3029 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3031 .getString("label.web_browser_not_found_unix"),
3032 MessageManager.getString("label.web_browser_not_found"),
3033 JvOptionPane.WARNING_MESSAGE);
3035 ex.printStackTrace();
3037 if (progress != null)
3039 progress.setProgressBar(null, this.hashCode());
3045 public static WsParamSetManager wsparamManager = null;
3047 public static ParamManager getUserParameterStore()
3049 if (wsparamManager == null)
3051 wsparamManager = new WsParamSetManager();
3053 return wsparamManager;
3057 * static hyperlink handler proxy method for use by Jalview's internal windows
3061 public static void hyperlinkUpdate(HyperlinkEvent e)
3063 if (e.getEventType() == EventType.ACTIVATED)
3068 url = e.getURL().toString();
3069 Desktop.showUrl(url);
3070 } catch (Exception x)
3074 if (Cache.log != null)
3076 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3080 System.err.println("Couldn't handle string " + url
3084 // ignore any exceptions due to dud links.
3091 * single thread that handles display of dialogs to user.
3093 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3096 * flag indicating if dialogExecutor should try to acquire a permit
3098 private volatile boolean dialogPause = true;
3103 private java.util.concurrent.Semaphore block = new Semaphore(0);
3105 private static groovy.ui.Console groovyConsole;
3108 * add another dialog thread to the queue
3112 public void addDialogThread(final Runnable prompter)
3114 dialogExecutor.submit(new Runnable()
3124 } catch (InterruptedException x)
3129 if (instance == null)
3135 SwingUtilities.invokeAndWait(prompter);
3136 } catch (Exception q)
3138 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3144 public void startDialogQueue()
3146 // set the flag so we don't pause waiting for another permit and semaphore
3147 // the current task to begin
3148 dialogPause = false;
3153 protected void snapShotWindow_actionPerformed(ActionEvent e)
3157 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3158 "View of Desktop", getWidth(), getHeight(), of = new File(
3159 "Jalview_snapshot" + System.currentTimeMillis()
3160 + ".eps"), "View of desktop", null, 0, false);
3163 paintAll(im.getGraphics());
3165 } catch (Exception q)
3167 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3171 Cache.log.info("Successfully written snapshot to file "
3172 + of.getAbsolutePath());
3176 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3177 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3178 * and location last time the view was expanded (if any). However it does not
3179 * remember the split pane divider location - this is set to match the
3180 * 'exploding' frame.
3184 public void explodeViews(SplitFrame sf)
3186 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3187 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3188 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3190 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3192 int viewCount = topPanels.size();
3199 * Processing in reverse order works, forwards order leaves the first panels
3200 * not visible. I don't know why!
3202 for (int i = viewCount - 1; i >= 0; i--)
3205 * Make new top and bottom frames. These take over the respective
3206 * AlignmentPanel objects, including their AlignmentViewports, so the
3207 * cdna/protein relationships between the viewports is carried over to the
3210 * explodedGeometry holds the (x, y) position of the previously exploded
3211 * SplitFrame, and the (width, height) of the AlignFrame component
3213 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3214 AlignFrame newTopFrame = new AlignFrame(topPanel);
3215 newTopFrame.setSize(oldTopFrame.getSize());
3216 newTopFrame.setVisible(true);
3217 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3218 .getExplodedGeometry();
3219 if (geometry != null)
3221 newTopFrame.setSize(geometry.getSize());
3224 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3225 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3226 newBottomFrame.setSize(oldBottomFrame.getSize());
3227 newBottomFrame.setVisible(true);
3228 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3229 .getExplodedGeometry();
3230 if (geometry != null)
3232 newBottomFrame.setSize(geometry.getSize());
3235 topPanel.av.setGatherViewsHere(false);
3236 bottomPanel.av.setGatherViewsHere(false);
3237 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3239 if (geometry != null)
3241 splitFrame.setLocation(geometry.getLocation());
3243 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3247 * Clear references to the panels (now relocated in the new SplitFrames)
3248 * before closing the old SplitFrame.
3251 bottomPanels.clear();
3256 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3257 * back into the given SplitFrame as additional views. Note that the gathered
3258 * frames may themselves have multiple views.
3262 public void gatherViews(GSplitFrame source)
3265 * special handling of explodedGeometry for a view within a SplitFrame: - it
3266 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3267 * height) of the AlignFrame component
3269 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3270 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3271 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3272 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3273 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3274 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3276 myTopFrame.viewport.setGatherViewsHere(true);
3277 myBottomFrame.viewport.setGatherViewsHere(true);
3278 String topViewId = myTopFrame.viewport.getSequenceSetId();
3279 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3281 JInternalFrame[] frames = desktop.getAllFrames();
3282 for (JInternalFrame frame : frames)
3284 if (frame instanceof SplitFrame && frame != source)
3286 SplitFrame sf = (SplitFrame) frame;
3287 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3288 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3289 boolean gatherThis = false;
3290 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3292 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3293 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3294 if (topViewId.equals(topPanel.av.getSequenceSetId())
3295 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3298 topPanel.av.setGatherViewsHere(false);
3299 bottomPanel.av.setGatherViewsHere(false);
3300 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3301 topFrame.getSize()));
3302 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3303 .getLocation(), bottomFrame.getSize()));
3304 myTopFrame.addAlignmentPanel(topPanel, false);
3305 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3311 topFrame.getAlignPanels().clear();
3312 bottomFrame.getAlignPanels().clear();
3319 * The dust settles...give focus to the tab we did this from.
3321 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3324 public static groovy.ui.Console getGroovyConsole()
3326 return groovyConsole;
3329 public static void transferFromDropTarget(List<String> files,
3330 List<DataSourceType> protocols, DropTargetDropEvent evt,
3335 DataFlavor uriListFlavor = new DataFlavor(
3336 "text/uri-list;class=java.lang.String");
3337 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3339 // Works on Windows and MacOSX
3340 Cache.log.debug("Drop handled as javaFileListFlavor");
3341 for (Object file : (List) t
3342 .getTransferData(DataFlavor.javaFileListFlavor))
3344 files.add(((File) file).toString());
3345 protocols.add(DataSourceType.FILE);
3350 // Unix like behaviour
3351 boolean added = false;
3353 if (t.isDataFlavorSupported(uriListFlavor))
3355 Cache.log.debug("Drop handled as uriListFlavor");
3356 // This is used by Unix drag system
3357 data = (String) t.getTransferData(uriListFlavor);
3361 // fallback to text: workaround - on OSX where there's a JVM bug
3362 Cache.log.debug("standard URIListFlavor failed. Trying text");
3363 // try text fallback
3364 data = (String) t.getTransferData(new DataFlavor(
3365 "text/plain;class=java.lang.String"));
3366 if (Cache.log.isDebugEnabled())
3368 Cache.log.debug("fallback returned " + data);
3371 while (protocols.size() < files.size())
3373 Cache.log.debug("Adding missing FILE protocol for "
3374 + files.get(protocols.size()));
3375 protocols.add(DataSourceType.FILE);
3377 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3378 data, "\r\n"); st.hasMoreTokens();)
3381 String s = st.nextToken();
3382 if (s.startsWith("#"))
3384 // the line is a comment (as per the RFC 2483)
3387 java.net.URI uri = new java.net.URI(s);
3388 if (uri.getScheme().toLowerCase().startsWith("http"))
3390 protocols.add(DataSourceType.URL);
3391 files.add(uri.toString());
3395 // otherwise preserve old behaviour: catch all for file objects
3396 java.io.File file = new java.io.File(uri);
3397 protocols.add(DataSourceType.FILE);
3398 files.add(file.toString());
3401 if (Cache.log.isDebugEnabled())
3403 if (data == null || !added)
3406 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3407 for (DataFlavor fl : t.getTransferDataFlavors())
3409 Cache.log.debug("Supported transfer dataflavor: "
3411 Object df = t.getTransferData(fl);
3414 Cache.log.debug("Retrieves: " + df);
3418 Cache.log.debug("Retrieved nothing");
3427 * Sets the Preferences property for experimental features to True or False
3428 * depending on the state of the controlling menu item
3431 protected void showExperimental_actionPerformed(boolean selected)
3433 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));