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()
364 : desktop.getDesktopManager())));
366 Rectangle dims = getLastKnownDimensions("");
373 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
374 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
377 jconsole = new Console(this, showjconsole);
378 // add essential build information
380 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
381 + "\n" + "Jalview Installation: "
382 + jalview.bin.Cache.getDefault("INSTALLATION",
384 + "\n" + "Build Date: "
385 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
386 + "\n" + "Java version: "
387 + System.getProperty("java.version") + "\n"
388 + System.getProperty("os.arch") + " "
389 + System.getProperty("os.name") + " "
390 + System.getProperty("os.version"));
392 showConsole(showjconsole);
394 showNews.setVisible(false);
396 experimentalFeatures.setSelected(showExperimental());
398 getIdentifiersOrgData();
402 this.addWindowListener(new WindowAdapter()
405 public void windowClosing(WindowEvent evt)
412 this.addMouseListener(ma = new MouseAdapter()
415 public void mousePressed(MouseEvent evt)
417 if (evt.isPopupTrigger()) // Mac
419 showPasteMenu(evt.getX(), evt.getY());
424 public void mouseReleased(MouseEvent evt)
426 if (evt.isPopupTrigger()) // Windows
428 showPasteMenu(evt.getX(), evt.getY());
432 desktop.addMouseListener(ma);
434 this.addFocusListener(new FocusListener()
438 public void focusLost(FocusEvent e)
440 // TODO Auto-generated method stub
445 public void focusGained(FocusEvent e)
447 Cache.log.debug("Relaying windows after focus gain");
448 // make sure that we sort windows properly after we gain focus
449 instance.relayerWindows();
452 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
453 // Spawn a thread that shows the splashscreen
454 SwingUtilities.invokeLater(new Runnable()
463 // Thread off a new instance of the file chooser - this reduces the time it
464 // takes to open it later on.
465 new Thread(new Runnable()
470 Cache.log.debug("Filechooser init thread started.");
471 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
472 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
474 Cache.log.debug("Filechooser init thread finished.");
477 // Add the service change listener
478 changeSupport.addJalviewPropertyChangeListener("services",
479 new PropertyChangeListener()
483 public void propertyChange(PropertyChangeEvent evt)
485 Cache.log.debug("Firing service changed event for "
486 + evt.getNewValue());
487 JalviewServicesChanged(evt);
494 * Answers true if user preferences to enable experimental features is True
499 public boolean showExperimental()
501 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
502 Boolean.FALSE.toString());
503 return Boolean.valueOf(experimental).booleanValue();
506 public void doConfigureStructurePrefs()
508 // configure services
509 StructureSelectionManager ssm = StructureSelectionManager
510 .getStructureSelectionManager(this);
511 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
513 ssm.setAddTempFacAnnot(jalview.bin.Cache
514 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
515 ssm.setProcessSecondaryStructure(jalview.bin.Cache
516 .getDefault(Preferences.STRUCT_FROM_PDB, true));
517 ssm.setSecStructServices(
518 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
522 ssm.setAddTempFacAnnot(false);
523 ssm.setProcessSecondaryStructure(false);
524 ssm.setSecStructServices(false);
528 public void checkForNews()
530 final Desktop me = this;
531 // Thread off the news reader, in case there are connection problems.
532 addDialogThread(new Runnable()
537 Cache.log.debug("Starting news thread.");
539 jvnews = new BlogReader(me);
540 showNews.setVisible(true);
541 Cache.log.debug("Completed news thread.");
546 public void getIdentifiersOrgData()
548 // Thread off the identifiers fetcher
549 addDialogThread(new Runnable()
554 Cache.log.debug("Downloading data from identifiers.org");
555 UrlDownloadClient client = new UrlDownloadClient();
558 client.download(IdOrgSettings.getUrl(),
559 IdOrgSettings.getDownloadLocation());
560 } catch (IOException e)
562 Cache.log.debug("Exception downloading identifiers.org data"
570 protected void showNews_actionPerformed(ActionEvent e)
572 showNews(showNews.isSelected());
575 void showNews(boolean visible)
578 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
579 showNews.setSelected(visible);
580 if (visible && !jvnews.isVisible())
582 new Thread(new Runnable()
587 long now = System.currentTimeMillis();
588 Desktop.instance.setProgressBar(
589 MessageManager.getString("status.refreshing_news"),
591 jvnews.refreshNews();
592 Desktop.instance.setProgressBar(null, now);
601 * recover the last known dimensions for a jalview window
604 * - empty string is desktop, all other windows have unique prefix
605 * @return null or last known dimensions scaled to current geometry (if last
606 * window geom was known)
608 Rectangle getLastKnownDimensions(String windowName)
610 // TODO: lock aspect ratio for scaling desktop Bug #0058199
611 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
612 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
613 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
614 String width = jalview.bin.Cache
615 .getProperty(windowName + "SCREEN_WIDTH");
616 String height = jalview.bin.Cache
617 .getProperty(windowName + "SCREEN_HEIGHT");
618 if ((x != null) && (y != null) && (width != null) && (height != null))
620 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
621 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
622 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
624 // attempt #1 - try to cope with change in screen geometry - this
625 // version doesn't preserve original jv aspect ratio.
626 // take ratio of current screen size vs original screen size.
627 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
628 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
629 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
630 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
631 // rescale the bounds depending upon the current screen geometry.
632 ix = (int) (ix * sw);
633 iw = (int) (iw * sw);
634 iy = (int) (iy * sh);
635 ih = (int) (ih * sh);
636 while (ix >= screenSize.width)
638 jalview.bin.Cache.log.debug(
639 "Window geometry location recall error: shifting horizontal to within screenbounds.");
640 ix -= screenSize.width;
642 while (iy >= screenSize.height)
644 jalview.bin.Cache.log.debug(
645 "Window geometry location recall error: shifting vertical to within screenbounds.");
646 iy -= screenSize.height;
648 jalview.bin.Cache.log.debug(
649 "Got last known dimensions for " + windowName + ": x:" + ix
650 + " y:" + iy + " width:" + iw + " height:" + ih);
652 // return dimensions for new instance
653 return new Rectangle(ix, iy, iw, ih);
658 private void doVamsasClientCheck()
660 if (jalview.bin.Cache.vamsasJarsPresent())
662 setupVamsasDisconnectedGui();
663 VamsasMenu.setVisible(true);
664 final Desktop us = this;
665 VamsasMenu.addMenuListener(new MenuListener()
667 // this listener remembers when the menu was first selected, and
668 // doesn't rebuild the session list until it has been cleared and
670 boolean refresh = true;
673 public void menuCanceled(MenuEvent e)
679 public void menuDeselected(MenuEvent e)
685 public void menuSelected(MenuEvent e)
689 us.buildVamsasStMenu();
694 vamsasStart.setVisible(true);
698 void showPasteMenu(int x, int y)
700 JPopupMenu popup = new JPopupMenu();
701 JMenuItem item = new JMenuItem(
702 MessageManager.getString("label.paste_new_window"));
703 item.addActionListener(new ActionListener()
706 public void actionPerformed(ActionEvent evt)
713 popup.show(this, x, y);
720 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
721 Transferable contents = c.getContents(this);
723 if (contents != null)
725 String file = (String) contents
726 .getTransferData(DataFlavor.stringFlavor);
728 FileFormatI format = new IdentifyFile().identify(file,
729 DataSourceType.PASTE);
731 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
734 } catch (Exception ex)
737 "Unable to paste alignment from system clipboard:\n" + ex);
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 // ///////////////////////////////////////////////
840 if (instance == null || (System.getProperty("java.awt.headless") != null
841 && System.getProperty("java.awt.headless").equals("true")))
850 frame.setMinimumSize(
851 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
853 // Set default dimension for Alignment Frame window.
854 // The Alignment Frame window could be added from a number of places,
856 // I did this here in order not to miss out on any Alignment frame.
857 if (frame instanceof AlignFrame)
859 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
860 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
864 frame.setVisible(makeVisible);
865 frame.setClosable(true);
866 frame.setResizable(resizable);
867 frame.setMaximizable(resizable);
868 frame.setIconifiable(resizable);
870 if (frame.getX() < 1 && frame.getY() < 1)
872 frame.setLocation(xOffset * openFrameCount,
873 yOffset * ((openFrameCount - 1) % 10) + yOffset);
877 * add an entry for the new frame in the Window menu
878 * (and remove it when the frame is closed)
880 final JMenuItem menuItem = new JMenuItem(title);
881 frame.addInternalFrameListener(new InternalFrameAdapter()
884 public void internalFrameActivated(InternalFrameEvent evt)
886 JInternalFrame itf = desktop.getSelectedFrame();
895 public void internalFrameClosed(InternalFrameEvent evt)
897 PaintRefresher.RemoveComponent(frame);
900 * defensive check to prevent frames being
901 * added half off the window
903 if (openFrameCount > 0)
909 * ensure no reference to alignFrame retained by menu item listener
911 if (menuItem.getActionListeners().length > 0)
913 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
915 windowMenu.remove(menuItem);
916 JInternalFrame itf = desktop.getSelectedFrame();
920 if (itf instanceof AlignFrame)
922 Jalview.setCurrentAlignFrame((AlignFrame) itf);
929 menuItem.addActionListener(new ActionListener()
932 public void actionPerformed(ActionEvent e)
936 frame.setSelected(true);
937 frame.setIcon(false);
938 } catch (java.beans.PropertyVetoException ex)
947 windowMenu.add(menuItem);
952 frame.setSelected(true);
953 frame.requestFocus();
954 } catch (java.beans.PropertyVetoException ve)
956 } catch (java.lang.ClassCastException cex)
959 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
965 public void lostOwnership(Clipboard clipboard, Transferable contents)
969 Desktop.jalviewClipboard = null;
972 internalCopy = false;
976 public void dragEnter(DropTargetDragEvent evt)
981 public void dragExit(DropTargetEvent evt)
986 public void dragOver(DropTargetDragEvent evt)
991 public void dropActionChanged(DropTargetDragEvent evt)
1002 public void drop(DropTargetDropEvent evt)
1004 boolean success = true;
1005 // JAL-1552 - acceptDrop required before getTransferable call for
1006 // Java's Transferable for native dnd
1007 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1008 Transferable t = evt.getTransferable();
1009 List<String> files = new ArrayList<>();
1010 List<DataSourceType> protocols = new ArrayList<>();
1014 Desktop.transferFromDropTarget(files, protocols, evt, t);
1015 } catch (Exception e)
1017 e.printStackTrace();
1025 for (int i = 0; i < files.size(); i++)
1027 String file = files.get(i).toString();
1028 DataSourceType protocol = (protocols == null)
1029 ? DataSourceType.FILE
1031 FileFormatI format = null;
1033 if (file.endsWith(".jar"))
1035 format = FileFormat.Jalview;
1040 format = new IdentifyFile().identify(file, protocol);
1043 new FileLoader().LoadFile(file, protocol, format);
1046 } catch (Exception ex)
1051 evt.dropComplete(success); // need this to ensure input focus is properly
1052 // transfered to any new windows created
1062 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1064 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1065 JalviewFileChooser chooser = JalviewFileChooser
1066 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1068 chooser.setFileView(new JalviewFileView());
1069 chooser.setDialogTitle(
1070 MessageManager.getString("label.open_local_file"));
1071 chooser.setToolTipText(MessageManager.getString("action.open"));
1073 int value = chooser.showOpenDialog(this);
1075 if (value == JalviewFileChooser.APPROVE_OPTION)
1077 String choice = chooser.getSelectedFile().getPath();
1078 Cache.setProperty("LAST_DIRECTORY",
1079 chooser.getSelectedFile().getParent());
1081 FileFormatI format = chooser.getSelectedFormat();
1084 * Call IdentifyFile to verify the file contains what its extension implies.
1085 * Skip this step for dynamically added file formats, because
1086 * IdentifyFile does not know how to recognise them.
1088 if (FileFormats.getInstance().isIdentifiable(format))
1092 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1093 } catch (FileFormatException e)
1095 // format = null; //??
1099 if (viewport != null)
1101 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1106 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1118 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1120 // This construct allows us to have a wider textfield
1122 JLabel label = new JLabel(
1123 MessageManager.getString("label.input_file_url"));
1124 final JComboBox history = new JComboBox();
1126 JPanel panel = new JPanel(new GridLayout(2, 1));
1129 history.setPreferredSize(new Dimension(400, 20));
1130 history.setEditable(true);
1131 history.addItem("http://www.");
1133 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1137 if (historyItems != null)
1139 st = new StringTokenizer(historyItems, "\t");
1141 while (st.hasMoreTokens())
1143 history.addItem(st.nextElement());
1147 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1148 MessageManager.getString("label.input_alignment_from_url"),
1149 JvOptionPane.OK_CANCEL_OPTION);
1151 if (reply != JvOptionPane.OK_OPTION)
1156 String url = history.getSelectedItem().toString();
1158 if (url.toLowerCase().endsWith(".jar"))
1160 if (viewport != null)
1162 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1163 FileFormat.Jalview);
1167 new FileLoader().LoadFile(url, DataSourceType.URL,
1168 FileFormat.Jalview);
1173 FileFormatI format = null;
1176 format = new IdentifyFile().identify(url, DataSourceType.URL);
1177 } catch (FileFormatException e)
1179 // TODO revise error handling, distinguish between
1180 // URL not found and response not valid
1185 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1186 MessageManager.formatMessage("label.couldnt_locate",
1189 MessageManager.getString("label.url_not_found"),
1190 JvOptionPane.WARNING_MESSAGE);
1195 if (viewport != null)
1197 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1202 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1208 * Opens the CutAndPaste window for the user to paste an alignment in to
1211 * - if not null, the pasted alignment is added to the current
1212 * alignment; if null, to a new alignment window
1215 public void inputTextboxMenuItem_actionPerformed(
1216 AlignmentViewPanel viewPanel)
1218 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1219 cap.setForInput(viewPanel);
1220 Desktop.addInternalFrame(cap,
1221 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1231 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1232 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1234 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1235 screen.height + "");
1236 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1237 getWidth(), getHeight()));
1239 if (jconsole != null)
1241 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1242 jconsole.stopConsole();
1246 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1249 if (dialogExecutor != null)
1251 dialogExecutor.shutdownNow();
1253 closeAll_actionPerformed(null);
1255 if (groovyConsole != null)
1257 // suppress a possible repeat prompt to save script
1258 groovyConsole.setDirty(false);
1259 groovyConsole.exit();
1264 private void storeLastKnownDimensions(String string, Rectangle jc)
1266 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1267 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1268 + " height:" + jc.height);
1270 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1271 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1272 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1273 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1283 public void aboutMenuItem_actionPerformed(ActionEvent e)
1285 // StringBuffer message = getAboutMessage(false);
1286 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1288 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1289 new Thread(new Runnable()
1294 new SplashScreen(true);
1299 public StringBuffer getAboutMessage(boolean shortv)
1301 StringBuffer message = new StringBuffer();
1302 message.append("<html>");
1305 message.append("<h1><strong>Version: "
1306 + jalview.bin.Cache.getProperty("VERSION")
1307 + "</strong></h1>");
1308 message.append("<strong>Last Updated: <em>"
1309 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1310 + "</em></strong>");
1316 message.append("<strong>Version "
1317 + jalview.bin.Cache.getProperty("VERSION")
1318 + "; last updated: "
1319 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1322 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1323 .equals("Checking"))
1325 message.append("<br>...Checking latest version...</br>");
1327 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1328 .equals(jalview.bin.Cache.getProperty("VERSION")))
1330 boolean red = false;
1331 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1332 .indexOf("automated build") == -1)
1335 // Displayed when code version and jnlp version do not match and code
1336 // version is not a development build
1337 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1340 message.append("<br>!! Version "
1341 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1343 + " is available for download from "
1344 + jalview.bin.Cache.getDefault("www.jalview.org",
1345 "http://www.jalview.org")
1349 message.append("</div>");
1352 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1354 "The Jalview Authors (See AUTHORS file for current list)")
1355 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1356 + "<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"
1357 + "<br><br>If you use Jalview, please cite:"
1358 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1359 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1360 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1372 public void documentationMenuItem_actionPerformed(ActionEvent e)
1376 Help.showHelpWindow();
1377 } catch (Exception ex)
1383 public void closeAll_actionPerformed(ActionEvent e)
1385 // TODO show a progress bar while closing?
1386 JInternalFrame[] frames = desktop.getAllFrames();
1387 for (int i = 0; i < frames.length; i++)
1391 frames[i].setClosed(true);
1392 } catch (java.beans.PropertyVetoException ex)
1396 Jalview.setCurrentAlignFrame(null);
1397 System.out.println("ALL CLOSED");
1398 if (v_client != null)
1400 // TODO clear binding to vamsas document objects on close_all
1404 * reset state of singleton objects as appropriate (clear down session state
1405 * when all windows are closed)
1407 StructureSelectionManager ssm = StructureSelectionManager
1408 .getStructureSelectionManager(this);
1417 public void raiseRelated_actionPerformed(ActionEvent e)
1419 reorderAssociatedWindows(false, false);
1423 public void minimizeAssociated_actionPerformed(ActionEvent e)
1425 reorderAssociatedWindows(true, false);
1428 void closeAssociatedWindows()
1430 reorderAssociatedWindows(false, true);
1436 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1440 protected void garbageCollect_actionPerformed(ActionEvent e)
1442 // We simply collect the garbage
1443 jalview.bin.Cache.log.debug("Collecting garbage...");
1445 jalview.bin.Cache.log.debug("Finished garbage collection.");
1452 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1456 protected void showMemusage_actionPerformed(ActionEvent e)
1458 desktop.showMemoryUsage(showMemusage.isSelected());
1465 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1469 protected void showConsole_actionPerformed(ActionEvent e)
1471 showConsole(showConsole.isSelected());
1474 Console jconsole = null;
1477 * control whether the java console is visible or not
1481 void showConsole(boolean selected)
1483 showConsole.setSelected(selected);
1484 // TODO: decide if we should update properties file
1485 Cache.setProperty("SHOW_JAVA_CONSOLE",
1486 Boolean.valueOf(selected).toString());
1487 jconsole.setVisible(selected);
1490 void reorderAssociatedWindows(boolean minimize, boolean close)
1492 JInternalFrame[] frames = desktop.getAllFrames();
1493 if (frames == null || frames.length < 1)
1498 AlignmentViewport source = null, target = null;
1499 if (frames[0] instanceof AlignFrame)
1501 source = ((AlignFrame) frames[0]).getCurrentView();
1503 else if (frames[0] instanceof TreePanel)
1505 source = ((TreePanel) frames[0]).getViewPort();
1507 else if (frames[0] instanceof PCAPanel)
1509 source = ((PCAPanel) frames[0]).av;
1511 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1513 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1518 for (int i = 0; i < frames.length; i++)
1521 if (frames[i] == null)
1525 if (frames[i] instanceof AlignFrame)
1527 target = ((AlignFrame) frames[i]).getCurrentView();
1529 else if (frames[i] instanceof TreePanel)
1531 target = ((TreePanel) frames[i]).getViewPort();
1533 else if (frames[i] instanceof PCAPanel)
1535 target = ((PCAPanel) frames[i]).av;
1537 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1539 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1542 if (source == target)
1548 frames[i].setClosed(true);
1552 frames[i].setIcon(minimize);
1555 frames[i].toFront();
1559 } catch (java.beans.PropertyVetoException ex)
1574 protected void preferences_actionPerformed(ActionEvent e)
1586 public void saveState_actionPerformed(ActionEvent e)
1588 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1591 chooser.setFileView(new JalviewFileView());
1592 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1594 int value = chooser.showSaveDialog(this);
1596 if (value == JalviewFileChooser.APPROVE_OPTION)
1598 final Desktop me = this;
1599 final java.io.File choice = chooser.getSelectedFile();
1600 setProjectFile(choice);
1602 new Thread(new Runnable()
1607 // TODO: refactor to Jalview desktop session controller action.
1608 setProgressBar(MessageManager.formatMessage(
1609 "label.saving_jalview_project", new Object[]
1610 { choice.getName() }), choice.hashCode());
1611 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1612 choice.getParent());
1613 // TODO catch and handle errors for savestate
1614 // TODO prevent user from messing with the Desktop whilst we're saving
1617 new Jalview2XML().saveState(choice);
1618 } catch (OutOfMemoryError oom)
1621 "Whilst saving current state to " + choice.getName(),
1623 } catch (Exception ex)
1626 "Problems whilst trying to save to " + choice.getName(),
1628 JvOptionPane.showMessageDialog(me,
1629 MessageManager.formatMessage(
1630 "label.error_whilst_saving_current_state_to",
1632 { choice.getName() }),
1633 MessageManager.getString("label.couldnt_save_project"),
1634 JvOptionPane.WARNING_MESSAGE);
1636 setProgressBar(null, choice.hashCode());
1642 private void setProjectFile(File choice)
1644 this.projectFile = choice;
1647 public File getProjectFile()
1649 return this.projectFile;
1659 public void loadState_actionPerformed(ActionEvent e)
1661 JalviewFileChooser chooser = new JalviewFileChooser(
1662 Cache.getProperty("LAST_DIRECTORY"), new String[]
1665 { "Jalview Project", "Jalview Project (old)" },
1667 chooser.setFileView(new JalviewFileView());
1668 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1670 int value = chooser.showOpenDialog(this);
1672 if (value == JalviewFileChooser.APPROVE_OPTION)
1674 final File selectedFile = chooser.getSelectedFile();
1675 setProjectFile(selectedFile);
1676 final String choice = selectedFile.getAbsolutePath();
1677 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1678 new Thread(new Runnable()
1683 setProgressBar(MessageManager.formatMessage(
1684 "label.loading_jalview_project", new Object[]
1685 { choice }), choice.hashCode());
1688 new Jalview2XML().loadJalviewAlign(choice);
1689 } catch (OutOfMemoryError oom)
1691 new OOMWarning("Whilst loading project from " + choice, oom);
1692 } catch (Exception ex)
1695 "Problems whilst loading project from " + choice, ex);
1696 JvOptionPane.showMessageDialog(Desktop.desktop,
1697 MessageManager.formatMessage(
1698 "label.error_whilst_loading_project_from",
1701 MessageManager.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<>();
1720 public void startLoading(final String fileName)
1722 if (fileLoadingCount == 0)
1724 fileLoadingPanels.add(addProgressPanel(MessageManager
1725 .formatMessage("label.loading_file", new Object[]
1731 private JPanel addProgressPanel(String string)
1733 if (progressPanel == null)
1735 progressPanel = new JPanel(new GridLayout(1, 1));
1736 totalProgressCount = 0;
1737 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1739 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1740 JProgressBar progressBar = new JProgressBar();
1741 progressBar.setIndeterminate(true);
1743 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1745 thisprogress.add(progressBar, BorderLayout.CENTER);
1746 progressPanel.add(thisprogress);
1747 ((GridLayout) progressPanel.getLayout()).setRows(
1748 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1749 ++totalProgressCount;
1750 instance.validate();
1751 return thisprogress;
1754 int totalProgressCount = 0;
1756 private void removeProgressPanel(JPanel progbar)
1758 if (progressPanel != null)
1760 synchronized (progressPanel)
1762 progressPanel.remove(progbar);
1763 GridLayout gl = (GridLayout) progressPanel.getLayout();
1764 gl.setRows(gl.getRows() - 1);
1765 if (--totalProgressCount < 1)
1767 this.getContentPane().remove(progressPanel);
1768 progressPanel = null;
1775 public void stopLoading()
1778 if (fileLoadingCount < 1)
1780 while (fileLoadingPanels.size() > 0)
1782 removeProgressPanel(fileLoadingPanels.remove(0));
1784 fileLoadingPanels.clear();
1785 fileLoadingCount = 0;
1790 public static int getViewCount(String alignmentId)
1792 AlignmentViewport[] aps = getViewports(alignmentId);
1793 return (aps == null) ? 0 : aps.length;
1798 * @param alignmentId
1799 * - if null, all sets are returned
1800 * @return all AlignmentPanels concerning the alignmentId sequence set
1802 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1804 if (Desktop.desktop == null)
1806 // no frames created and in headless mode
1807 // TODO: verify that frames are recoverable when in headless mode
1810 List<AlignmentPanel> aps = new ArrayList<>();
1811 AlignFrame[] frames = getAlignFrames();
1816 for (AlignFrame af : frames)
1818 for (AlignmentPanel ap : af.alignPanels)
1820 if (alignmentId == null
1821 || alignmentId.equals(ap.av.getSequenceSetId()))
1827 if (aps.size() == 0)
1831 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1836 * get all the viewports on an alignment.
1838 * @param sequenceSetId
1839 * unique alignment id (may be null - all viewports returned in that
1841 * @return all viewports on the alignment bound to sequenceSetId
1843 public static AlignmentViewport[] getViewports(String sequenceSetId)
1845 List<AlignmentViewport> viewp = new ArrayList<>();
1846 if (desktop != null)
1848 AlignFrame[] frames = Desktop.getAlignFrames();
1850 for (AlignFrame afr : frames)
1852 if (sequenceSetId == null || 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(
1976 MessageManager.getString("label.open_saved_vamsas_session"));
1977 chooser.setToolTipText(MessageManager.getString(
1978 "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()))
1987 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1988 MessageManager.formatMessage(
1989 "label.couldnt_import_as_vamsas_session",
1993 .getString("label.vamsas_document_import_failed"),
1994 JvOptionPane.ERROR_MESSAGE);
2000 jalview.bin.Cache.log.error(
2001 "Implementation error - load session from a running session is not supported.");
2006 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2009 * @return true if import was a success and a session was started.
2011 public boolean vamsasImport(URL url)
2013 // TODO: create progress bar
2014 if (v_client != null)
2017 jalview.bin.Cache.log.error(
2018 "Implementation error - load session from a running session is not supported.");
2024 // copy the URL content to a temporary local file
2025 // TODO: be a bit cleverer here with nio (?!)
2026 File file = File.createTempFile("vdocfromurl", ".vdj");
2027 FileOutputStream fos = new FileOutputStream(file);
2028 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2029 byte[] buffer = new byte[2048];
2031 while ((ln = bis.read(buffer)) > -1)
2033 fos.write(buffer, 0, ln);
2037 v_client = new jalview.gui.VamsasApplication(this, file,
2038 url.toExternalForm());
2039 } catch (Exception ex)
2041 jalview.bin.Cache.log.error(
2042 "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.error(
2064 "Implementation error - load session from a running session is not supported.");
2068 setProgressBar(MessageManager.formatMessage(
2069 "status.importing_vamsas_session_from", new Object[]
2070 { 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", new Object[]
2078 { 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", new Object[]
2087 { file.getName() }), file.hashCode());
2088 return v_client.inSession();
2091 public boolean joinVamsasSession(String mysesid)
2093 if (v_client != null)
2095 throw new Error(MessageManager
2096 .getString("error.try_join_vamsas_session_another"));
2098 if (mysesid == null)
2101 MessageManager.getString("error.invalid_vamsas_session_id"));
2103 v_client = new VamsasApplication(this, mysesid);
2104 setupVamsasConnectedGui();
2105 v_client.initial_update();
2106 return (v_client.inSession());
2110 public void vamsasStart_actionPerformed(ActionEvent e)
2112 if (v_client == null)
2115 // we just start a default session for moment.
2117 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2118 * getProperty("LAST_DIRECTORY"));
2120 * chooser.setFileView(new JalviewFileView());
2121 * chooser.setDialogTitle("Load Vamsas file");
2122 * chooser.setToolTipText("Import");
2124 * int value = chooser.showOpenDialog(this);
2126 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2127 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2129 v_client = new VamsasApplication(this);
2130 setupVamsasConnectedGui();
2131 v_client.initial_update(); // TODO: thread ?
2135 // store current data in session.
2136 v_client.push_update(); // TODO: thread
2140 protected void setupVamsasConnectedGui()
2142 vamsasStart.setText(MessageManager.getString("label.session_update"));
2143 vamsasSave.setVisible(true);
2144 vamsasStop.setVisible(true);
2145 vamsasImport.setVisible(false); // Document import to existing session is
2146 // not possible for vamsas-client-1.0.
2149 protected void setupVamsasDisconnectedGui()
2151 vamsasSave.setVisible(false);
2152 vamsasStop.setVisible(false);
2153 vamsasImport.setVisible(true);
2155 .setText(MessageManager.getString("label.new_vamsas_session"));
2159 public void vamsasStop_actionPerformed(ActionEvent e)
2161 if (v_client != null)
2163 v_client.end_session();
2165 setupVamsasDisconnectedGui();
2169 protected void buildVamsasStMenu()
2171 if (v_client == null)
2173 String[] sess = null;
2176 sess = VamsasApplication.getSessionList();
2177 } catch (Exception e)
2179 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2185 jalview.bin.Cache.log.debug(
2186 "Got current sessions list: " + sess.length + " entries.");
2187 VamsasStMenu.removeAll();
2188 for (int i = 0; i < sess.length; i++)
2190 JMenuItem sessit = new JMenuItem();
2191 sessit.setText(sess[i]);
2192 sessit.setToolTipText(MessageManager
2193 .formatMessage("label.connect_to_session", new Object[]
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
2260 .formatMessage("label.saving_vamsas_doc", new Object[]
2261 { 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
2273 .error("Error Whilst saving document to " + choice, ex);
2275 } catch (Exception ex)
2277 warnttl = "Problem saving Vamsas Document.";
2278 warnmsg = ex.toString();
2279 jalview.bin.Cache.log.warn(
2280 "Exception Whilst saving document to " + choice, ex);
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(
2314 MessageManager.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<>();
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
2368 : link.substring(0, barPos) + ": "
2369 + link.substring(barPos + 1);
2370 urls.add(new JLabel(urlMsg));
2378 // ask user to check in case URL links use old style tokens
2379 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2380 JPanel msgPanel = new JPanel();
2381 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2382 msgPanel.add(Box.createVerticalGlue());
2383 JLabel msg = new JLabel(MessageManager
2384 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2385 JLabel msg2 = new JLabel(MessageManager
2386 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2388 for (JLabel url : urls)
2394 final JCheckBox jcb = new JCheckBox(
2395 MessageManager.getString("label.do_not_display_again"));
2396 jcb.addActionListener(new ActionListener()
2399 public void actionPerformed(ActionEvent e)
2401 // update Cache settings for "don't show this again"
2402 boolean showWarningAgain = !jcb.isSelected();
2403 Cache.setProperty("CHECKURLLINKS",
2404 Boolean.valueOf(showWarningAgain).toString());
2409 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2411 .getString("label.SEQUENCE_ID_no_longer_used"),
2412 JvOptionPane.WARNING_MESSAGE);
2419 * Proxy class for JDesktopPane which optionally displays the current memory
2420 * usage and highlights the desktop area with a red bar if free memory runs
2425 public class MyDesktopPane extends JDesktopPane implements Runnable
2428 private static final float ONE_MB = 1048576f;
2430 boolean showMemoryUsage = false;
2434 java.text.NumberFormat df;
2436 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2439 public MyDesktopPane(boolean showMemoryUsage)
2441 showMemoryUsage(showMemoryUsage);
2444 public void showMemoryUsage(boolean showMemory)
2446 this.showMemoryUsage = showMemory;
2449 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("label.memory_stats",
2508 { df.format(totalFreeMemory), df.format(maxMemory),
2509 df.format(percentUsage) }),
2510 10, 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<>();
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<>();
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)
2678 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2679 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2681 getRootPane().getActionMap().put("Quit", new AbstractAction()
2684 public void actionPerformed(ActionEvent e)
2692 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2695 * true if Groovy console is open
2697 public void enableExecuteGroovy(boolean enabled)
2700 * disable opening a second Groovy console
2701 * (or re-enable when the console is closed)
2703 groovyShell.setEnabled(!enabled);
2705 AlignFrame[] alignFrames = getAlignFrames();
2706 if (alignFrames != null)
2708 for (AlignFrame af : alignFrames)
2710 af.setGroovyEnabled(enabled);
2716 * Progress bars managed by the IProgressIndicator method.
2718 private Hashtable<Long, JPanel> progressBars;
2720 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2725 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2728 public void setProgressBar(String message, long id)
2730 if (progressBars == null)
2732 progressBars = new Hashtable<>();
2733 progressBarHandlers = new Hashtable<>();
2736 if (progressBars.get(new Long(id)) != null)
2738 JPanel panel = progressBars.remove(new Long(id));
2739 if (progressBarHandlers.contains(new Long(id)))
2741 progressBarHandlers.remove(new Long(id));
2743 removeProgressPanel(panel);
2747 progressBars.put(new Long(id), addProgressPanel(message));
2754 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2755 * jalview.gui.IProgressIndicatorHandler)
2758 public void registerHandler(final long id,
2759 final IProgressIndicatorHandler handler)
2761 if (progressBarHandlers == null
2762 || !progressBars.containsKey(new Long(id)))
2764 throw new Error(MessageManager.getString(
2765 "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
2782 .formatMessage("label.cancelled_params", new Object[]
2783 { ((JLabel) progressPanel.getComponent(0)).getText() }),
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(
2818 viewport.getSequenceSetId());
2819 for (int panel = 0; aps != null && panel < aps.length; panel++)
2821 if (aps[panel] != null && aps[panel].av == viewport)
2823 return aps[panel].alignFrame;
2830 public VamsasApplication getVamsasApplication()
2837 * flag set if jalview GUI is being operated programmatically
2839 private boolean inBatchMode = false;
2842 * check if jalview GUI is being operated programmatically
2844 * @return inBatchMode
2846 public boolean isInBatchMode()
2852 * set flag if jalview GUI is being operated programmatically
2854 * @param inBatchMode
2856 public void setInBatchMode(boolean inBatchMode)
2858 this.inBatchMode = inBatchMode;
2861 public void startServiceDiscovery()
2863 startServiceDiscovery(false);
2866 public void startServiceDiscovery(boolean blocking)
2868 boolean alive = true;
2869 Thread t0 = null, t1 = null, t2 = null;
2870 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2873 // todo: changesupport handlers need to be transferred
2874 if (discoverer == null)
2876 discoverer = new jalview.ws.jws1.Discoverer();
2877 // register PCS handler for desktop.
2878 discoverer.addPropertyChangeListener(changeSupport);
2880 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2881 // until we phase out completely
2882 (t0 = new Thread(discoverer)).start();
2885 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2887 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2888 .startDiscoverer(changeSupport);
2892 // TODO: do rest service discovery
2901 } catch (Exception e)
2904 alive = (t1 != null && t1.isAlive()) || (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();
2959 JvOptionPane.showConfirmDialog(Desktop.desktop,
2960 new JLabel("<html><table width=\"450\"><tr><td>"
2961 + ermsg + "</td></tr></table>"
2962 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2963 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2964 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2965 + " Tools->Preferences dialog box to change them.</p></html>"),
2966 "Web Service Configuration Problem",
2967 JvOptionPane.DEFAULT_OPTION,
2968 JvOptionPane.ERROR_MESSAGE);
2969 serviceChangedDialog = null;
2978 "Errors reported by JABA discovery service. Check web services preferences.\n"
2985 private Runnable serviceChangedDialog = null;
2988 * start a thread to open a URL in the configured browser. Pops up a warning
2989 * dialog to the user if there is an exception when calling out to the browser
2994 public static void showUrl(final String url)
2996 showUrl(url, Desktop.instance);
3000 * Like showUrl but allows progress handler to be specified
3004 * (null) or object implementing IProgressIndicator
3006 public static void showUrl(final String url,
3007 final IProgressIndicator progress)
3009 new Thread(new Runnable()
3016 if (progress != null)
3018 progress.setProgressBar(MessageManager
3019 .formatMessage("status.opening_params", new Object[]
3020 { url }), this.hashCode());
3022 jalview.util.BrowserLauncher.openURL(url);
3023 } catch (Exception ex)
3025 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3027 .getString("label.web_browser_not_found_unix"),
3028 MessageManager.getString("label.web_browser_not_found"),
3029 JvOptionPane.WARNING_MESSAGE);
3031 ex.printStackTrace();
3033 if (progress != null)
3035 progress.setProgressBar(null, this.hashCode());
3041 public static WsParamSetManager wsparamManager = null;
3043 public static ParamManager getUserParameterStore()
3045 if (wsparamManager == null)
3047 wsparamManager = new WsParamSetManager();
3049 return wsparamManager;
3053 * static hyperlink handler proxy method for use by Jalview's internal windows
3057 public static void hyperlinkUpdate(HyperlinkEvent e)
3059 if (e.getEventType() == EventType.ACTIVATED)
3064 url = e.getURL().toString();
3065 Desktop.showUrl(url);
3066 } catch (Exception x)
3070 if (Cache.log != null)
3072 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3077 "Couldn't handle string " + url + " as a URL.");
3080 // ignore any exceptions due to dud links.
3087 * single thread that handles display of dialogs to user.
3089 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3092 * flag indicating if dialogExecutor should try to acquire a permit
3094 private volatile boolean dialogPause = true;
3099 private java.util.concurrent.Semaphore block = new Semaphore(0);
3101 private static groovy.ui.Console groovyConsole;
3104 * add another dialog thread to the queue
3108 public void addDialogThread(final Runnable prompter)
3110 dialogExecutor.submit(new Runnable()
3120 } catch (InterruptedException x)
3125 if (instance == null)
3131 SwingUtilities.invokeAndWait(prompter);
3132 } catch (Exception q)
3134 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3140 public void startDialogQueue()
3142 // set the flag so we don't pause waiting for another permit and semaphore
3143 // the current task to begin
3144 dialogPause = false;
3149 protected void snapShotWindow_actionPerformed(ActionEvent e)
3153 ImageMaker im = new jalview.util.ImageMaker(
3154 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3155 getHeight(), of = new File("Jalview_snapshot"
3156 + System.currentTimeMillis() + ".eps"),
3157 "View of desktop", null, 0, false);
3160 paintAll(im.getGraphics());
3162 } catch (Exception q)
3164 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3168 Cache.log.info("Successfully written snapshot to file "
3169 + of.getAbsolutePath());
3173 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3174 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3175 * and location last time the view was expanded (if any). However it does not
3176 * remember the split pane divider location - this is set to match the
3177 * 'exploding' frame.
3181 public void explodeViews(SplitFrame sf)
3183 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3184 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3185 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3187 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3189 int viewCount = topPanels.size();
3196 * Processing in reverse order works, forwards order leaves the first panels
3197 * not visible. I don't know why!
3199 for (int i = viewCount - 1; i >= 0; i--)
3202 * Make new top and bottom frames. These take over the respective
3203 * AlignmentPanel objects, including their AlignmentViewports, so the
3204 * cdna/protein relationships between the viewports is carried over to the
3207 * explodedGeometry holds the (x, y) position of the previously exploded
3208 * SplitFrame, and the (width, height) of the AlignFrame component
3210 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3211 AlignFrame newTopFrame = new AlignFrame(topPanel);
3212 newTopFrame.setSize(oldTopFrame.getSize());
3213 newTopFrame.setVisible(true);
3214 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3215 .getExplodedGeometry();
3216 if (geometry != null)
3218 newTopFrame.setSize(geometry.getSize());
3221 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3222 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3223 newBottomFrame.setSize(oldBottomFrame.getSize());
3224 newBottomFrame.setVisible(true);
3225 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3226 .getExplodedGeometry();
3227 if (geometry != null)
3229 newBottomFrame.setSize(geometry.getSize());
3232 topPanel.av.setGatherViewsHere(false);
3233 bottomPanel.av.setGatherViewsHere(false);
3234 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3236 if (geometry != null)
3238 splitFrame.setLocation(geometry.getLocation());
3240 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3244 * Clear references to the panels (now relocated in the new SplitFrames)
3245 * before closing the old SplitFrame.
3248 bottomPanels.clear();
3253 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3254 * back into the given SplitFrame as additional views. Note that the gathered
3255 * frames may themselves have multiple views.
3259 public void gatherViews(GSplitFrame source)
3262 * special handling of explodedGeometry for a view within a SplitFrame: - it
3263 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3264 * height) of the AlignFrame component
3266 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3267 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3268 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3269 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3270 myBottomFrame.viewport
3271 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3272 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3273 myTopFrame.viewport.setGatherViewsHere(true);
3274 myBottomFrame.viewport.setGatherViewsHere(true);
3275 String topViewId = myTopFrame.viewport.getSequenceSetId();
3276 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3278 JInternalFrame[] frames = desktop.getAllFrames();
3279 for (JInternalFrame frame : frames)
3281 if (frame instanceof SplitFrame && frame != source)
3283 SplitFrame sf = (SplitFrame) frame;
3284 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3285 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3286 boolean gatherThis = false;
3287 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3289 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3290 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3291 if (topViewId.equals(topPanel.av.getSequenceSetId())
3292 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3295 topPanel.av.setGatherViewsHere(false);
3296 bottomPanel.av.setGatherViewsHere(false);
3297 topPanel.av.setExplodedGeometry(
3298 new Rectangle(sf.getLocation(), topFrame.getSize()));
3299 bottomPanel.av.setExplodedGeometry(
3300 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3301 myTopFrame.addAlignmentPanel(topPanel, false);
3302 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3308 topFrame.getAlignPanels().clear();
3309 bottomFrame.getAlignPanels().clear();
3316 * The dust settles...give focus to the tab we did this from.
3318 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3321 public static groovy.ui.Console getGroovyConsole()
3323 return groovyConsole;
3326 public static void transferFromDropTarget(List<String> files,
3327 List<DataSourceType> protocols, DropTargetDropEvent evt,
3328 Transferable t) throws Exception
3331 DataFlavor uriListFlavor = new DataFlavor(
3332 "text/uri-list;class=java.lang.String");
3333 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3335 // Works on Windows and MacOSX
3336 Cache.log.debug("Drop handled as javaFileListFlavor");
3337 for (Object file : (List) t
3338 .getTransferData(DataFlavor.javaFileListFlavor))
3340 files.add(((File) file).toString());
3341 protocols.add(DataSourceType.FILE);
3346 // Unix like behaviour
3347 boolean added = false;
3349 if (t.isDataFlavorSupported(uriListFlavor))
3351 Cache.log.debug("Drop handled as uriListFlavor");
3352 // This is used by Unix drag system
3353 data = (String) t.getTransferData(uriListFlavor);
3357 // fallback to text: workaround - on OSX where there's a JVM bug
3358 Cache.log.debug("standard URIListFlavor failed. Trying text");
3359 // try text fallback
3360 data = (String) t.getTransferData(
3361 new DataFlavor("text/plain;class=java.lang.String"));
3362 if (Cache.log.isDebugEnabled())
3364 Cache.log.debug("fallback returned " + data);
3367 while (protocols.size() < files.size())
3369 Cache.log.debug("Adding missing FILE protocol for "
3370 + files.get(protocols.size()));
3371 protocols.add(DataSourceType.FILE);
3373 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3374 data, "\r\n"); st.hasMoreTokens();)
3377 String s = st.nextToken();
3378 if (s.startsWith("#"))
3380 // the line is a comment (as per the RFC 2483)
3383 java.net.URI uri = new java.net.URI(s);
3384 if (uri.getScheme().toLowerCase().startsWith("http"))
3386 protocols.add(DataSourceType.URL);
3387 files.add(uri.toString());
3391 // otherwise preserve old behaviour: catch all for file objects
3392 java.io.File file = new java.io.File(uri);
3393 protocols.add(DataSourceType.FILE);
3394 files.add(file.toString());
3397 if (Cache.log.isDebugEnabled())
3399 if (data == null || !added)
3402 "Couldn't resolve drop data. Here are the supported flavors:");
3403 for (DataFlavor fl : t.getTransferDataFlavors())
3406 "Supported transfer dataflavor: " + fl.toString());
3407 Object df = t.getTransferData(fl);
3410 Cache.log.debug("Retrieves: " + df);
3414 Cache.log.debug("Retrieved nothing");
3423 * Sets the Preferences property for experimental features to True or False
3424 * depending on the state of the controlling menu item
3427 protected void showExperimental_actionPerformed(boolean selected)
3429 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));