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();
894 public void internalFrameClosed(InternalFrameEvent evt)
896 PaintRefresher.RemoveComponent(frame);
899 * defensive check to prevent frames being
900 * added half off the window
902 if (openFrameCount > 0)
908 * ensure no reference to alignFrame retained by menu item listener
910 if (menuItem.getActionListeners().length > 0)
912 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
914 windowMenu.remove(menuItem);
915 JInternalFrame itf = desktop.getSelectedFrame();
919 if (itf instanceof AlignFrame)
921 Jalview.setCurrentAlignFrame((AlignFrame) itf);
928 menuItem.addActionListener(new ActionListener()
931 public void actionPerformed(ActionEvent e)
935 frame.setSelected(true);
936 frame.setIcon(false);
937 } catch (java.beans.PropertyVetoException ex)
946 windowMenu.add(menuItem);
951 frame.setSelected(true);
952 frame.requestFocus();
953 } catch (java.beans.PropertyVetoException ve)
955 } catch (java.lang.ClassCastException cex)
958 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
964 public void lostOwnership(Clipboard clipboard, Transferable contents)
968 Desktop.jalviewClipboard = null;
971 internalCopy = false;
975 public void dragEnter(DropTargetDragEvent evt)
980 public void dragExit(DropTargetEvent evt)
985 public void dragOver(DropTargetDragEvent evt)
990 public void dropActionChanged(DropTargetDragEvent evt)
1001 public void drop(DropTargetDropEvent evt)
1003 boolean success = true;
1004 // JAL-1552 - acceptDrop required before getTransferable call for
1005 // Java's Transferable for native dnd
1006 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1007 Transferable t = evt.getTransferable();
1008 List<String> files = new ArrayList<>();
1009 List<DataSourceType> protocols = new ArrayList<>();
1013 Desktop.transferFromDropTarget(files, protocols, evt, t);
1014 } catch (Exception e)
1016 e.printStackTrace();
1024 for (int i = 0; i < files.size(); i++)
1026 String file = files.get(i).toString();
1027 DataSourceType protocol = (protocols == null)
1028 ? DataSourceType.FILE
1030 FileFormatI format = null;
1032 if (file.endsWith(".jar"))
1034 format = FileFormat.Jalview;
1039 format = new IdentifyFile().identify(file, protocol);
1042 new FileLoader().LoadFile(file, protocol, format);
1045 } catch (Exception ex)
1050 evt.dropComplete(success); // need this to ensure input focus is properly
1051 // transfered to any new windows created
1061 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1063 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1064 JalviewFileChooser chooser = JalviewFileChooser
1065 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1067 chooser.setFileView(new JalviewFileView());
1068 chooser.setDialogTitle(
1069 MessageManager.getString("label.open_local_file"));
1070 chooser.setToolTipText(MessageManager.getString("action.open"));
1072 int value = chooser.showOpenDialog(this);
1074 if (value == JalviewFileChooser.APPROVE_OPTION)
1076 String choice = chooser.getSelectedFile().getPath();
1077 Cache.setProperty("LAST_DIRECTORY",
1078 chooser.getSelectedFile().getParent());
1080 FileFormatI format = chooser.getSelectedFormat();
1083 * Call IdentifyFile to verify the file contains what its extension implies.
1084 * Skip this step for dynamically added file formats, because
1085 * IdentifyFile does not know how to recognise them.
1087 if (FileFormats.getInstance().isIdentifiable(format))
1091 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1092 } catch (FileFormatException e)
1094 // format = null; //??
1098 if (viewport != null)
1100 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1105 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1117 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1119 // This construct allows us to have a wider textfield
1121 JLabel label = new JLabel(
1122 MessageManager.getString("label.input_file_url"));
1123 final JComboBox history = new JComboBox();
1125 JPanel panel = new JPanel(new GridLayout(2, 1));
1128 history.setPreferredSize(new Dimension(400, 20));
1129 history.setEditable(true);
1130 history.addItem("http://www.");
1132 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1136 if (historyItems != null)
1138 st = new StringTokenizer(historyItems, "\t");
1140 while (st.hasMoreTokens())
1142 history.addItem(st.nextElement());
1146 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1147 MessageManager.getString("label.input_alignment_from_url"),
1148 JvOptionPane.OK_CANCEL_OPTION);
1150 if (reply != JvOptionPane.OK_OPTION)
1155 String url = history.getSelectedItem().toString();
1157 if (url.toLowerCase().endsWith(".jar"))
1159 if (viewport != null)
1161 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1162 FileFormat.Jalview);
1166 new FileLoader().LoadFile(url, DataSourceType.URL,
1167 FileFormat.Jalview);
1172 FileFormatI format = null;
1175 format = new IdentifyFile().identify(url, DataSourceType.URL);
1176 } catch (FileFormatException e)
1178 // TODO revise error handling, distinguish between
1179 // URL not found and response not valid
1184 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1185 MessageManager.formatMessage("label.couldnt_locate",
1188 MessageManager.getString("label.url_not_found"),
1189 JvOptionPane.WARNING_MESSAGE);
1194 if (viewport != null)
1196 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1201 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1207 * Opens the CutAndPaste window for the user to paste an alignment in to
1210 * - if not null, the pasted alignment is added to the current
1211 * alignment; if null, to a new alignment window
1214 public void inputTextboxMenuItem_actionPerformed(
1215 AlignmentViewPanel viewPanel)
1217 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1218 cap.setForInput(viewPanel);
1219 Desktop.addInternalFrame(cap,
1220 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1230 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1231 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1233 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1234 screen.height + "");
1235 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1236 getWidth(), getHeight()));
1238 if (jconsole != null)
1240 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1241 jconsole.stopConsole();
1245 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1248 if (dialogExecutor != null)
1250 dialogExecutor.shutdownNow();
1252 closeAll_actionPerformed(null);
1254 if (groovyConsole != null)
1256 // suppress a possible repeat prompt to save script
1257 groovyConsole.setDirty(false);
1258 groovyConsole.exit();
1263 private void storeLastKnownDimensions(String string, Rectangle jc)
1265 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1266 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1267 + " height:" + jc.height);
1269 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1270 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1271 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1272 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1282 public void aboutMenuItem_actionPerformed(ActionEvent e)
1284 // StringBuffer message = getAboutMessage(false);
1285 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1287 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1288 new Thread(new Runnable()
1293 new SplashScreen(true);
1298 public StringBuffer getAboutMessage(boolean shortv)
1300 StringBuffer message = new StringBuffer();
1301 message.append("<html>");
1304 message.append("<h1><strong>Version: "
1305 + jalview.bin.Cache.getProperty("VERSION")
1306 + "</strong></h1>");
1307 message.append("<strong>Last Updated: <em>"
1308 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1309 + "</em></strong>");
1315 message.append("<strong>Version "
1316 + jalview.bin.Cache.getProperty("VERSION")
1317 + "; last updated: "
1318 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1321 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1322 .equals("Checking"))
1324 message.append("<br>...Checking latest version...</br>");
1326 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1327 .equals(jalview.bin.Cache.getProperty("VERSION")))
1329 boolean red = false;
1330 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1331 .indexOf("automated build") == -1)
1334 // Displayed when code version and jnlp version do not match and code
1335 // version is not a development build
1336 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1339 message.append("<br>!! Version "
1340 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1342 + " is available for download from "
1343 + jalview.bin.Cache.getDefault("www.jalview.org",
1344 "http://www.jalview.org")
1348 message.append("</div>");
1351 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1353 "The Jalview Authors (See AUTHORS file for current list)")
1354 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1355 + "<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"
1356 + "<br><br>If you use Jalview, please cite:"
1357 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1358 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1359 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1371 public void documentationMenuItem_actionPerformed(ActionEvent e)
1375 Help.showHelpWindow();
1376 } catch (Exception ex)
1382 public void closeAll_actionPerformed(ActionEvent e)
1384 // TODO show a progress bar while closing?
1385 JInternalFrame[] frames = desktop.getAllFrames();
1386 for (int i = 0; i < frames.length; i++)
1390 frames[i].setClosed(true);
1391 } catch (java.beans.PropertyVetoException ex)
1395 Jalview.setCurrentAlignFrame(null);
1396 System.out.println("ALL CLOSED");
1397 if (v_client != null)
1399 // TODO clear binding to vamsas document objects on close_all
1403 * reset state of singleton objects as appropriate (clear down session state
1404 * when all windows are closed)
1406 StructureSelectionManager ssm = StructureSelectionManager
1407 .getStructureSelectionManager(this);
1416 public void raiseRelated_actionPerformed(ActionEvent e)
1418 reorderAssociatedWindows(false, false);
1422 public void minimizeAssociated_actionPerformed(ActionEvent e)
1424 reorderAssociatedWindows(true, false);
1427 void closeAssociatedWindows()
1429 reorderAssociatedWindows(false, true);
1435 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1439 protected void garbageCollect_actionPerformed(ActionEvent e)
1441 // We simply collect the garbage
1442 jalview.bin.Cache.log.debug("Collecting garbage...");
1444 jalview.bin.Cache.log.debug("Finished garbage collection.");
1451 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1455 protected void showMemusage_actionPerformed(ActionEvent e)
1457 desktop.showMemoryUsage(showMemusage.isSelected());
1464 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1468 protected void showConsole_actionPerformed(ActionEvent e)
1470 showConsole(showConsole.isSelected());
1473 Console jconsole = null;
1476 * control whether the java console is visible or not
1480 void showConsole(boolean selected)
1482 showConsole.setSelected(selected);
1483 // TODO: decide if we should update properties file
1484 Cache.setProperty("SHOW_JAVA_CONSOLE",
1485 Boolean.valueOf(selected).toString());
1486 jconsole.setVisible(selected);
1489 void reorderAssociatedWindows(boolean minimize, boolean close)
1491 JInternalFrame[] frames = desktop.getAllFrames();
1492 if (frames == null || frames.length < 1)
1497 AlignmentViewport source = null, target = null;
1498 if (frames[0] instanceof AlignFrame)
1500 source = ((AlignFrame) frames[0]).getCurrentView();
1502 else if (frames[0] instanceof TreePanel)
1504 source = ((TreePanel) frames[0]).getViewPort();
1506 else if (frames[0] instanceof PCAPanel)
1508 source = ((PCAPanel) frames[0]).av;
1510 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1512 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1517 for (int i = 0; i < frames.length; i++)
1520 if (frames[i] == null)
1524 if (frames[i] instanceof AlignFrame)
1526 target = ((AlignFrame) frames[i]).getCurrentView();
1528 else if (frames[i] instanceof TreePanel)
1530 target = ((TreePanel) frames[i]).getViewPort();
1532 else if (frames[i] instanceof PCAPanel)
1534 target = ((PCAPanel) frames[i]).av;
1536 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1538 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1541 if (source == target)
1547 frames[i].setClosed(true);
1551 frames[i].setIcon(minimize);
1554 frames[i].toFront();
1558 } catch (java.beans.PropertyVetoException ex)
1573 protected void preferences_actionPerformed(ActionEvent e)
1585 public void saveState_actionPerformed(ActionEvent e)
1587 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1590 chooser.setFileView(new JalviewFileView());
1591 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1593 int value = chooser.showSaveDialog(this);
1595 if (value == JalviewFileChooser.APPROVE_OPTION)
1597 final Desktop me = this;
1598 final java.io.File choice = chooser.getSelectedFile();
1599 setProjectFile(choice);
1601 new Thread(new Runnable()
1606 // TODO: refactor to Jalview desktop session controller action.
1607 setProgressBar(MessageManager.formatMessage(
1608 "label.saving_jalview_project", new Object[]
1609 { choice.getName() }), choice.hashCode());
1610 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1611 choice.getParent());
1612 // TODO catch and handle errors for savestate
1613 // TODO prevent user from messing with the Desktop whilst we're saving
1616 new Jalview2XML().saveState(choice);
1617 } catch (OutOfMemoryError oom)
1620 "Whilst saving current state to " + choice.getName(),
1622 } catch (Exception ex)
1625 "Problems whilst trying to save to " + choice.getName(),
1627 JvOptionPane.showMessageDialog(me,
1628 MessageManager.formatMessage(
1629 "label.error_whilst_saving_current_state_to",
1631 { choice.getName() }),
1632 MessageManager.getString("label.couldnt_save_project"),
1633 JvOptionPane.WARNING_MESSAGE);
1635 setProgressBar(null, choice.hashCode());
1641 private void setProjectFile(File choice)
1643 this.projectFile = choice;
1646 public File getProjectFile()
1648 return this.projectFile;
1658 public void loadState_actionPerformed(ActionEvent e)
1660 JalviewFileChooser chooser = new JalviewFileChooser(
1661 Cache.getProperty("LAST_DIRECTORY"), new String[]
1664 { "Jalview Project", "Jalview Project (old)" },
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", selectedFile.getParent());
1677 new Thread(new Runnable()
1682 setProgressBar(MessageManager.formatMessage(
1683 "label.loading_jalview_project", new Object[]
1684 { choice }), choice.hashCode());
1687 new Jalview2XML().loadJalviewAlign(choice);
1688 } catch (OutOfMemoryError oom)
1690 new OOMWarning("Whilst loading project from " + choice, oom);
1691 } catch (Exception ex)
1694 "Problems whilst loading project from " + choice, ex);
1695 JvOptionPane.showMessageDialog(Desktop.desktop,
1696 MessageManager.formatMessage(
1697 "label.error_whilst_loading_project_from",
1700 MessageManager.getString("label.couldnt_load_project"),
1701 JvOptionPane.WARNING_MESSAGE);
1703 setProgressBar(null, choice.hashCode());
1710 public void inputSequence_actionPerformed(ActionEvent e)
1712 new SequenceFetcher(this);
1715 JPanel progressPanel;
1717 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1719 public void startLoading(final String fileName)
1721 if (fileLoadingCount == 0)
1723 fileLoadingPanels.add(addProgressPanel(MessageManager
1724 .formatMessage("label.loading_file", new Object[]
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()).setRows(
1747 ((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<>();
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<>();
1845 if (desktop != null)
1847 AlignFrame[] frames = Desktop.getAlignFrames();
1849 for (AlignFrame afr : frames)
1851 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1852 .equals(sequenceSetId))
1854 if (afr.alignPanels != null)
1856 for (AlignmentPanel ap : afr.alignPanels)
1858 if (sequenceSetId == null
1859 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1867 viewp.add(afr.getViewport());
1871 if (viewp.size() > 0)
1873 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1880 * Explode the views in the given frame into separate AlignFrame
1884 public static void explodeViews(AlignFrame af)
1886 int size = af.alignPanels.size();
1892 for (int i = 0; i < size; i++)
1894 AlignmentPanel ap = af.alignPanels.get(i);
1895 AlignFrame newaf = new AlignFrame(ap);
1898 * Restore the view's last exploded frame geometry if known. Multiple
1899 * views from one exploded frame share and restore the same (frame)
1900 * position and size.
1902 Rectangle geometry = ap.av.getExplodedGeometry();
1903 if (geometry != null)
1905 newaf.setBounds(geometry);
1908 ap.av.setGatherViewsHere(false);
1910 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1911 AlignFrame.DEFAULT_HEIGHT);
1914 af.alignPanels.clear();
1915 af.closeMenuItem_actionPerformed(true);
1920 * Gather expanded views (separate AlignFrame's) with the same sequence set
1921 * identifier back in to this frame as additional views, and close the
1922 * expanded views. Note the expanded frames may themselves have multiple
1923 * views. We take the lot.
1927 public void gatherViews(AlignFrame source)
1929 source.viewport.setGatherViewsHere(true);
1930 source.viewport.setExplodedGeometry(source.getBounds());
1931 JInternalFrame[] frames = desktop.getAllFrames();
1932 String viewId = source.viewport.getSequenceSetId();
1934 for (int t = 0; t < frames.length; t++)
1936 if (frames[t] instanceof AlignFrame && frames[t] != source)
1938 AlignFrame af = (AlignFrame) frames[t];
1939 boolean gatherThis = false;
1940 for (int a = 0; a < af.alignPanels.size(); a++)
1942 AlignmentPanel ap = af.alignPanels.get(a);
1943 if (viewId.equals(ap.av.getSequenceSetId()))
1946 ap.av.setGatherViewsHere(false);
1947 ap.av.setExplodedGeometry(af.getBounds());
1948 source.addAlignmentPanel(ap, false);
1954 af.alignPanels.clear();
1955 af.closeMenuItem_actionPerformed(true);
1962 jalview.gui.VamsasApplication v_client = null;
1965 public void vamsasImport_actionPerformed(ActionEvent e)
1967 if (v_client == null)
1969 // Load and try to start a session.
1970 JalviewFileChooser chooser = new JalviewFileChooser(
1971 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1973 chooser.setFileView(new JalviewFileView());
1974 chooser.setDialogTitle(
1975 MessageManager.getString("label.open_saved_vamsas_session"));
1976 chooser.setToolTipText(MessageManager.getString(
1977 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1979 int value = chooser.showOpenDialog(this);
1981 if (value == JalviewFileChooser.APPROVE_OPTION)
1983 String fle = chooser.getSelectedFile().toString();
1984 if (!vamsasImport(chooser.getSelectedFile()))
1986 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1987 MessageManager.formatMessage(
1988 "label.couldnt_import_as_vamsas_session",
1992 .getString("label.vamsas_document_import_failed"),
1993 JvOptionPane.ERROR_MESSAGE);
1999 jalview.bin.Cache.log.error(
2000 "Implementation error - load session from a running session is not supported.");
2005 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2008 * @return true if import was a success and a session was started.
2010 public boolean vamsasImport(URL url)
2012 // TODO: create progress bar
2013 if (v_client != null)
2016 jalview.bin.Cache.log.error(
2017 "Implementation error - load session from a running session is not supported.");
2023 // copy the URL content to a temporary local file
2024 // TODO: be a bit cleverer here with nio (?!)
2025 File file = File.createTempFile("vdocfromurl", ".vdj");
2026 FileOutputStream fos = new FileOutputStream(file);
2027 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2028 byte[] buffer = new byte[2048];
2030 while ((ln = bis.read(buffer)) > -1)
2032 fos.write(buffer, 0, ln);
2036 v_client = new jalview.gui.VamsasApplication(this, file,
2037 url.toExternalForm());
2038 } catch (Exception ex)
2040 jalview.bin.Cache.log.error(
2041 "Failed to create new vamsas session from contents of URL "
2046 setupVamsasConnectedGui();
2047 v_client.initial_update(); // TODO: thread ?
2048 return v_client.inSession();
2052 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2055 * @return true if import was a success and a session was started.
2057 public boolean vamsasImport(File file)
2059 if (v_client != null)
2062 jalview.bin.Cache.log.error(
2063 "Implementation error - load session from a running session is not supported.");
2067 setProgressBar(MessageManager.formatMessage(
2068 "status.importing_vamsas_session_from", new Object[]
2069 { file.getName() }), file.hashCode());
2072 v_client = new jalview.gui.VamsasApplication(this, file, null);
2073 } catch (Exception ex)
2075 setProgressBar(MessageManager.formatMessage(
2076 "status.importing_vamsas_session_from", new Object[]
2077 { file.getName() }), file.hashCode());
2078 jalview.bin.Cache.log.error(
2079 "New vamsas session from existing session file failed:", ex);
2082 setupVamsasConnectedGui();
2083 v_client.initial_update(); // TODO: thread ?
2084 setProgressBar(MessageManager.formatMessage(
2085 "status.importing_vamsas_session_from", new Object[]
2086 { file.getName() }), file.hashCode());
2087 return v_client.inSession();
2090 public boolean joinVamsasSession(String mysesid)
2092 if (v_client != null)
2094 throw new Error(MessageManager
2095 .getString("error.try_join_vamsas_session_another"));
2097 if (mysesid == null)
2100 MessageManager.getString("error.invalid_vamsas_session_id"));
2102 v_client = new VamsasApplication(this, mysesid);
2103 setupVamsasConnectedGui();
2104 v_client.initial_update();
2105 return (v_client.inSession());
2109 public void vamsasStart_actionPerformed(ActionEvent e)
2111 if (v_client == null)
2114 // we just start a default session for moment.
2116 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2117 * getProperty("LAST_DIRECTORY"));
2119 * chooser.setFileView(new JalviewFileView());
2120 * chooser.setDialogTitle("Load Vamsas file");
2121 * chooser.setToolTipText("Import");
2123 * int value = chooser.showOpenDialog(this);
2125 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2126 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2128 v_client = new VamsasApplication(this);
2129 setupVamsasConnectedGui();
2130 v_client.initial_update(); // TODO: thread ?
2134 // store current data in session.
2135 v_client.push_update(); // TODO: thread
2139 protected void setupVamsasConnectedGui()
2141 vamsasStart.setText(MessageManager.getString("label.session_update"));
2142 vamsasSave.setVisible(true);
2143 vamsasStop.setVisible(true);
2144 vamsasImport.setVisible(false); // Document import to existing session is
2145 // not possible for vamsas-client-1.0.
2148 protected void setupVamsasDisconnectedGui()
2150 vamsasSave.setVisible(false);
2151 vamsasStop.setVisible(false);
2152 vamsasImport.setVisible(true);
2154 .setText(MessageManager.getString("label.new_vamsas_session"));
2158 public void vamsasStop_actionPerformed(ActionEvent e)
2160 if (v_client != null)
2162 v_client.end_session();
2164 setupVamsasDisconnectedGui();
2168 protected void buildVamsasStMenu()
2170 if (v_client == null)
2172 String[] sess = null;
2175 sess = VamsasApplication.getSessionList();
2176 } catch (Exception e)
2178 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2184 jalview.bin.Cache.log.debug(
2185 "Got current sessions list: " + sess.length + " entries.");
2186 VamsasStMenu.removeAll();
2187 for (int i = 0; i < sess.length; i++)
2189 JMenuItem sessit = new JMenuItem();
2190 sessit.setText(sess[i]);
2191 sessit.setToolTipText(MessageManager
2192 .formatMessage("label.connect_to_session", new Object[]
2194 final Desktop dsktp = this;
2195 final String mysesid = sess[i];
2196 sessit.addActionListener(new ActionListener()
2200 public void actionPerformed(ActionEvent e)
2202 if (dsktp.v_client == null)
2204 Thread rthr = new Thread(new Runnable()
2210 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2211 dsktp.setupVamsasConnectedGui();
2212 dsktp.v_client.initial_update();
2220 VamsasStMenu.add(sessit);
2222 // don't show an empty menu.
2223 VamsasStMenu.setVisible(sess.length > 0);
2228 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2229 VamsasStMenu.removeAll();
2230 VamsasStMenu.setVisible(false);
2235 // Not interested in the content. Just hide ourselves.
2236 VamsasStMenu.setVisible(false);
2241 public void vamsasSave_actionPerformed(ActionEvent e)
2243 if (v_client != null)
2245 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2246 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2249 chooser.setFileView(new JalviewFileView());
2250 chooser.setDialogTitle(MessageManager
2251 .getString("label.save_vamsas_document_archive"));
2253 int value = chooser.showSaveDialog(this);
2255 if (value == JalviewFileChooser.APPROVE_OPTION)
2257 java.io.File choice = chooser.getSelectedFile();
2258 JPanel progpanel = addProgressPanel(MessageManager
2259 .formatMessage("label.saving_vamsas_doc", new Object[]
2260 { choice.getName() }));
2261 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2262 String warnmsg = null;
2263 String warnttl = null;
2266 v_client.vclient.storeDocument(choice);
2269 warnttl = "Serious Problem saving Vamsas Document";
2270 warnmsg = ex.toString();
2271 jalview.bin.Cache.log
2272 .error("Error Whilst saving document to " + choice, ex);
2274 } catch (Exception ex)
2276 warnttl = "Problem saving Vamsas Document.";
2277 warnmsg = ex.toString();
2278 jalview.bin.Cache.log.warn(
2279 "Exception Whilst saving document to " + choice, ex);
2282 removeProgressPanel(progpanel);
2283 if (warnmsg != null)
2285 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2287 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2293 JPanel vamUpdate = null;
2296 * hide vamsas user gui bits when a vamsas document event is being handled.
2299 * true to hide gui, false to reveal gui
2301 public void setVamsasUpdate(boolean b)
2303 Cache.log.debug("Setting gui for Vamsas update "
2304 + (b ? "in progress" : "finished"));
2306 if (vamUpdate != null)
2308 this.removeProgressPanel(vamUpdate);
2312 vamUpdate = this.addProgressPanel(
2313 MessageManager.getString("label.updating_vamsas_session"));
2315 vamsasStart.setVisible(!b);
2316 vamsasStop.setVisible(!b);
2317 vamsasSave.setVisible(!b);
2320 public JInternalFrame[] getAllFrames()
2322 return desktop.getAllFrames();
2326 * Checks the given url to see if it gives a response indicating that the user
2327 * should be informed of a new questionnaire.
2331 public void checkForQuestionnaire(String url)
2333 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2334 // javax.swing.SwingUtilities.invokeLater(jvq);
2335 new Thread(jvq).start();
2338 public void checkURLLinks()
2340 // Thread off the URL link checker
2341 addDialogThread(new Runnable()
2346 if (Cache.getDefault("CHECKURLLINKS", true))
2348 // check what the actual links are - if it's just the default don't
2349 // bother with the warning
2350 List<String> links = Preferences.sequenceUrlLinks
2353 // only need to check links if there is one with a
2354 // SEQUENCE_ID which is not the default EMBL_EBI link
2355 ListIterator<String> li = links.listIterator();
2356 boolean check = false;
2357 List<JLabel> urls = new ArrayList<>();
2358 while (li.hasNext())
2360 String link = li.next();
2361 if (link.contains(SEQUENCE_ID)
2362 && !link.equals(UrlConstants.DEFAULT_STRING))
2365 int barPos = link.indexOf("|");
2366 String urlMsg = barPos == -1 ? link
2367 : link.substring(0, barPos) + ": "
2368 + 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(MessageManager
2383 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2384 JLabel msg2 = new JLabel(MessageManager
2385 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2387 for (JLabel url : urls)
2393 final JCheckBox jcb = new JCheckBox(
2394 MessageManager.getString("label.do_not_display_again"));
2395 jcb.addActionListener(new ActionListener()
2398 public void actionPerformed(ActionEvent e)
2400 // update Cache settings for "don't show this again"
2401 boolean showWarningAgain = !jcb.isSelected();
2402 Cache.setProperty("CHECKURLLINKS",
2403 Boolean.valueOf(showWarningAgain).toString());
2408 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2410 .getString("label.SEQUENCE_ID_no_longer_used"),
2411 JvOptionPane.WARNING_MESSAGE);
2418 * Proxy class for JDesktopPane which optionally displays the current memory
2419 * usage and highlights the desktop area with a red bar if free memory runs
2424 public class MyDesktopPane extends JDesktopPane implements Runnable
2427 private static final float ONE_MB = 1048576f;
2429 boolean showMemoryUsage = false;
2433 java.text.NumberFormat df;
2435 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2438 public MyDesktopPane(boolean showMemoryUsage)
2440 showMemoryUsage(showMemoryUsage);
2443 public void showMemoryUsage(boolean showMemory)
2445 this.showMemoryUsage = showMemory;
2448 Thread worker = new Thread(this);
2454 public boolean isShowMemoryUsage()
2456 return showMemoryUsage;
2462 df = java.text.NumberFormat.getNumberInstance();
2463 df.setMaximumFractionDigits(2);
2464 runtime = Runtime.getRuntime();
2466 while (showMemoryUsage)
2470 maxMemory = runtime.maxMemory() / ONE_MB;
2471 allocatedMemory = runtime.totalMemory() / ONE_MB;
2472 freeMemory = runtime.freeMemory() / ONE_MB;
2473 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2475 percentUsage = (totalFreeMemory / maxMemory) * 100;
2477 // if (percentUsage < 20)
2479 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2481 // instance.set.setBorder(border1);
2484 // sleep after showing usage
2486 } catch (Exception ex)
2488 ex.printStackTrace();
2494 public void paintComponent(Graphics g)
2496 if (showMemoryUsage && g != null && df != null)
2498 if (percentUsage < 20)
2500 g.setColor(Color.red);
2502 FontMetrics fm = g.getFontMetrics();
2505 g.drawString(MessageManager.formatMessage("label.memory_stats",
2507 { df.format(totalFreeMemory), df.format(maxMemory),
2508 df.format(percentUsage) }),
2509 10, getHeight() - fm.getHeight());
2516 * fixes stacking order after a modal dialog to ensure windows that should be
2517 * on top actually are
2519 public void relayerWindows()
2525 * Accessor method to quickly get all the AlignmentFrames loaded.
2527 * @return an array of AlignFrame, or null if none found
2529 public static AlignFrame[] getAlignFrames()
2531 if (Jalview.isHeadlessMode())
2533 // Desktop.desktop is null in headless mode
2534 return new AlignFrame[] { Jalview.currentAlignFrame };
2537 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2543 List<AlignFrame> avp = new ArrayList<>();
2545 for (int i = frames.length - 1; i > -1; i--)
2547 if (frames[i] instanceof AlignFrame)
2549 avp.add((AlignFrame) frames[i]);
2551 else if (frames[i] instanceof SplitFrame)
2554 * Also check for a split frame containing an AlignFrame
2556 GSplitFrame sf = (GSplitFrame) frames[i];
2557 if (sf.getTopFrame() instanceof AlignFrame)
2559 avp.add((AlignFrame) sf.getTopFrame());
2561 if (sf.getBottomFrame() instanceof AlignFrame)
2563 avp.add((AlignFrame) sf.getBottomFrame());
2567 if (avp.size() == 0)
2571 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2576 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2580 public GStructureViewer[] getJmols()
2582 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2588 List<GStructureViewer> avp = new ArrayList<>();
2590 for (int i = frames.length - 1; i > -1; i--)
2592 if (frames[i] instanceof AppJmol)
2594 GStructureViewer af = (GStructureViewer) frames[i];
2598 if (avp.size() == 0)
2602 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2607 * Add Groovy Support to Jalview
2610 public void groovyShell_actionPerformed()
2614 openGroovyConsole();
2615 } catch (Exception ex)
2617 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2618 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2620 MessageManager.getString("label.couldnt_create_groovy_shell"),
2621 MessageManager.getString("label.groovy_support_failed"),
2622 JvOptionPane.ERROR_MESSAGE);
2627 * Open the Groovy console
2629 void openGroovyConsole()
2631 if (groovyConsole == null)
2633 groovyConsole = new groovy.ui.Console();
2634 groovyConsole.setVariable("Jalview", this);
2635 groovyConsole.run();
2638 * We allow only one console at a time, so that AlignFrame menu option
2639 * 'Calculate | Run Groovy script' is unambiguous.
2640 * Disable 'Groovy Console', and enable 'Run script', when the console is
2641 * opened, and the reverse when it is closed
2643 Window window = (Window) groovyConsole.getFrame();
2644 window.addWindowListener(new WindowAdapter()
2647 public void windowClosed(WindowEvent e)
2650 * rebind CMD-Q from Groovy Console to Jalview Quit
2653 enableExecuteGroovy(false);
2659 * show Groovy console window (after close and reopen)
2661 ((Window) groovyConsole.getFrame()).setVisible(true);
2664 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2665 * and disable opening a second console
2667 enableExecuteGroovy(true);
2671 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2672 * binding when opened
2674 protected void addQuitHandler()
2676 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2677 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2678 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
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<>();
2732 progressBarHandlers = new Hashtable<>();
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)))
2763 throw new Error(MessageManager.getString(
2764 "error.call_setprogressbar_before_registering_handler"));
2766 progressBarHandlers.put(new Long(id), handler);
2767 final JPanel progressPanel = progressBars.get(new Long(id));
2768 if (handler.canCancel())
2770 JButton cancel = new JButton(
2771 MessageManager.getString("action.cancel"));
2772 final IProgressIndicator us = this;
2773 cancel.addActionListener(new ActionListener()
2777 public void actionPerformed(ActionEvent e)
2779 handler.cancelActivity(id);
2780 us.setProgressBar(MessageManager
2781 .formatMessage("label.cancelled_params", new Object[]
2782 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2786 progressPanel.add(cancel, BorderLayout.EAST);
2792 * @return true if any progress bars are still active
2795 public boolean operationInProgress()
2797 if (progressBars != null && progressBars.size() > 0)
2805 * This will return the first AlignFrame holding the given viewport instance.
2806 * It will break if there are more than one AlignFrames viewing a particular
2810 * @return alignFrame for viewport
2812 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2814 if (desktop != null)
2816 AlignmentPanel[] aps = getAlignmentPanels(
2817 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()
2887 .startDiscoverer(changeSupport);
2891 // TODO: do rest service discovery
2900 } catch (Exception e)
2903 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2904 || (t3 != null && t3.isAlive())
2905 || (t0 != null && t0.isAlive());
2911 * called to check if the service discovery process completed successfully.
2915 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2917 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2919 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2920 .getErrorMessages();
2923 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2925 if (serviceChangedDialog == null)
2927 // only run if we aren't already displaying one of these.
2928 addDialogThread(serviceChangedDialog = new Runnable()
2935 * JalviewDialog jd =new JalviewDialog() {
2937 * @Override protected void cancelPressed() { // TODO
2938 * Auto-generated method stub
2940 * }@Override protected void okPressed() { // TODO
2941 * Auto-generated method stub
2943 * }@Override protected void raiseClosed() { // TODO
2944 * Auto-generated method stub
2946 * } }; jd.initDialogFrame(new
2947 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2948 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2949 * + " or mis-configured HTTP proxy settings.<br/>" +
2950 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2952 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2953 * ), true, true, "Web Service Configuration Problem", 450,
2956 * jd.waitForInput();
2958 JvOptionPane.showConfirmDialog(Desktop.desktop,
2959 new JLabel("<html><table width=\"450\"><tr><td>"
2960 + ermsg + "</td></tr></table>"
2961 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2962 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2963 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2964 + " Tools->Preferences dialog box to change them.</p></html>"),
2965 "Web Service Configuration Problem",
2966 JvOptionPane.DEFAULT_OPTION,
2967 JvOptionPane.ERROR_MESSAGE);
2968 serviceChangedDialog = null;
2977 "Errors reported by JABA discovery service. Check web services preferences.\n"
2984 private Runnable serviceChangedDialog = null;
2987 * start a thread to open a URL in the configured browser. Pops up a warning
2988 * dialog to the user if there is an exception when calling out to the browser
2993 public static void showUrl(final String url)
2995 showUrl(url, Desktop.instance);
2999 * Like showUrl but allows progress handler to be specified
3003 * (null) or object implementing IProgressIndicator
3005 public static void showUrl(final String url,
3006 final IProgressIndicator progress)
3008 new Thread(new Runnable()
3015 if (progress != null)
3017 progress.setProgressBar(MessageManager
3018 .formatMessage("status.opening_params", new Object[]
3019 { url }), this.hashCode());
3021 jalview.util.BrowserLauncher.openURL(url);
3022 } catch (Exception ex)
3024 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3026 .getString("label.web_browser_not_found_unix"),
3027 MessageManager.getString("label.web_browser_not_found"),
3028 JvOptionPane.WARNING_MESSAGE);
3030 ex.printStackTrace();
3032 if (progress != null)
3034 progress.setProgressBar(null, this.hashCode());
3040 public static WsParamSetManager wsparamManager = null;
3042 public static ParamManager getUserParameterStore()
3044 if (wsparamManager == null)
3046 wsparamManager = new WsParamSetManager();
3048 return wsparamManager;
3052 * static hyperlink handler proxy method for use by Jalview's internal windows
3056 public static void hyperlinkUpdate(HyperlinkEvent e)
3058 if (e.getEventType() == EventType.ACTIVATED)
3063 url = e.getURL().toString();
3064 Desktop.showUrl(url);
3065 } catch (Exception x)
3069 if (Cache.log != null)
3071 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3076 "Couldn't handle string " + url + " as a URL.");
3079 // ignore any exceptions due to dud links.
3086 * single thread that handles display of dialogs to user.
3088 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3091 * flag indicating if dialogExecutor should try to acquire a permit
3093 private volatile boolean dialogPause = true;
3098 private java.util.concurrent.Semaphore block = new Semaphore(0);
3100 private static groovy.ui.Console groovyConsole;
3103 * add another dialog thread to the queue
3107 public void addDialogThread(final Runnable prompter)
3109 dialogExecutor.submit(new Runnable()
3119 } catch (InterruptedException x)
3124 if (instance == null)
3130 SwingUtilities.invokeAndWait(prompter);
3131 } catch (Exception q)
3133 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3139 public void startDialogQueue()
3141 // set the flag so we don't pause waiting for another permit and semaphore
3142 // the current task to begin
3143 dialogPause = false;
3148 protected void snapShotWindow_actionPerformed(ActionEvent e)
3152 ImageMaker im = new jalview.util.ImageMaker(
3153 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3154 getHeight(), of = new File("Jalview_snapshot"
3155 + System.currentTimeMillis() + ".eps"),
3156 "View of desktop", null, 0, false);
3159 paintAll(im.getGraphics());
3161 } catch (Exception q)
3163 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3167 Cache.log.info("Successfully written snapshot to file "
3168 + of.getAbsolutePath());
3172 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3173 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3174 * and location last time the view was expanded (if any). However it does not
3175 * remember the split pane divider location - this is set to match the
3176 * 'exploding' frame.
3180 public void explodeViews(SplitFrame sf)
3182 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3183 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3184 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3186 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3188 int viewCount = topPanels.size();
3195 * Processing in reverse order works, forwards order leaves the first panels
3196 * not visible. I don't know why!
3198 for (int i = viewCount - 1; i >= 0; i--)
3201 * Make new top and bottom frames. These take over the respective
3202 * AlignmentPanel objects, including their AlignmentViewports, so the
3203 * cdna/protein relationships between the viewports is carried over to the
3206 * explodedGeometry holds the (x, y) position of the previously exploded
3207 * SplitFrame, and the (width, height) of the AlignFrame component
3209 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3210 AlignFrame newTopFrame = new AlignFrame(topPanel);
3211 newTopFrame.setSize(oldTopFrame.getSize());
3212 newTopFrame.setVisible(true);
3213 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3214 .getExplodedGeometry();
3215 if (geometry != null)
3217 newTopFrame.setSize(geometry.getSize());
3220 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3221 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3222 newBottomFrame.setSize(oldBottomFrame.getSize());
3223 newBottomFrame.setVisible(true);
3224 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3225 .getExplodedGeometry();
3226 if (geometry != null)
3228 newBottomFrame.setSize(geometry.getSize());
3231 topPanel.av.setGatherViewsHere(false);
3232 bottomPanel.av.setGatherViewsHere(false);
3233 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3235 if (geometry != null)
3237 splitFrame.setLocation(geometry.getLocation());
3239 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3243 * Clear references to the panels (now relocated in the new SplitFrames)
3244 * before closing the old SplitFrame.
3247 bottomPanels.clear();
3252 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3253 * back into the given SplitFrame as additional views. Note that the gathered
3254 * frames may themselves have multiple views.
3258 public void gatherViews(GSplitFrame source)
3261 * special handling of explodedGeometry for a view within a SplitFrame: - it
3262 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3263 * height) of the AlignFrame component
3265 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3266 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3267 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3268 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3269 myBottomFrame.viewport
3270 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3271 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3272 myTopFrame.viewport.setGatherViewsHere(true);
3273 myBottomFrame.viewport.setGatherViewsHere(true);
3274 String topViewId = myTopFrame.viewport.getSequenceSetId();
3275 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3277 JInternalFrame[] frames = desktop.getAllFrames();
3278 for (JInternalFrame frame : frames)
3280 if (frame instanceof SplitFrame && frame != source)
3282 SplitFrame sf = (SplitFrame) frame;
3283 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3284 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3285 boolean gatherThis = false;
3286 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3288 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3289 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3290 if (topViewId.equals(topPanel.av.getSequenceSetId())
3291 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3294 topPanel.av.setGatherViewsHere(false);
3295 bottomPanel.av.setGatherViewsHere(false);
3296 topPanel.av.setExplodedGeometry(
3297 new Rectangle(sf.getLocation(), topFrame.getSize()));
3298 bottomPanel.av.setExplodedGeometry(
3299 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3300 myTopFrame.addAlignmentPanel(topPanel, false);
3301 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3307 topFrame.getAlignPanels().clear();
3308 bottomFrame.getAlignPanels().clear();
3315 * The dust settles...give focus to the tab we did this from.
3317 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3320 public static groovy.ui.Console getGroovyConsole()
3322 return groovyConsole;
3325 public static void transferFromDropTarget(List<String> files,
3326 List<DataSourceType> protocols, DropTargetDropEvent evt,
3327 Transferable t) throws Exception
3330 DataFlavor uriListFlavor = new DataFlavor(
3331 "text/uri-list;class=java.lang.String");
3332 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3334 // Works on Windows and MacOSX
3335 Cache.log.debug("Drop handled as javaFileListFlavor");
3336 for (Object file : (List) t
3337 .getTransferData(DataFlavor.javaFileListFlavor))
3339 files.add(((File) file).toString());
3340 protocols.add(DataSourceType.FILE);
3345 // Unix like behaviour
3346 boolean added = false;
3348 if (t.isDataFlavorSupported(uriListFlavor))
3350 Cache.log.debug("Drop handled as uriListFlavor");
3351 // This is used by Unix drag system
3352 data = (String) t.getTransferData(uriListFlavor);
3356 // fallback to text: workaround - on OSX where there's a JVM bug
3357 Cache.log.debug("standard URIListFlavor failed. Trying text");
3358 // try text fallback
3359 data = (String) t.getTransferData(
3360 new DataFlavor("text/plain;class=java.lang.String"));
3361 if (Cache.log.isDebugEnabled())
3363 Cache.log.debug("fallback returned " + data);
3366 while (protocols.size() < files.size())
3368 Cache.log.debug("Adding missing FILE protocol for "
3369 + files.get(protocols.size()));
3370 protocols.add(DataSourceType.FILE);
3372 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3373 data, "\r\n"); st.hasMoreTokens();)
3376 String s = st.nextToken();
3377 if (s.startsWith("#"))
3379 // the line is a comment (as per the RFC 2483)
3382 java.net.URI uri = new java.net.URI(s);
3383 if (uri.getScheme().toLowerCase().startsWith("http"))
3385 protocols.add(DataSourceType.URL);
3386 files.add(uri.toString());
3390 // otherwise preserve old behaviour: catch all for file objects
3391 java.io.File file = new java.io.File(uri);
3392 protocols.add(DataSourceType.FILE);
3393 files.add(file.toString());
3396 if (Cache.log.isDebugEnabled())
3398 if (data == null || !added)
3401 "Couldn't resolve drop data. Here are the supported flavors:");
3402 for (DataFlavor fl : t.getTransferDataFlavors())
3405 "Supported transfer dataflavor: " + fl.toString());
3406 Object df = t.getTransferData(fl);
3409 Cache.log.debug("Retrieves: " + df);
3413 Cache.log.debug("Retrieved nothing");
3422 * Sets the Preferences property for experimental features to True or False
3423 * depending on the state of the controlling menu item
3426 protected void showExperimental_actionPerformed(boolean selected)
3428 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));