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.UrlConstants;
45 import jalview.viewmodel.AlignmentViewport;
46 import jalview.ws.params.ParamManager;
47 import jalview.ws.utils.UrlDownloadClient;
49 import java.awt.BorderLayout;
50 import java.awt.Color;
51 import java.awt.Dimension;
52 import java.awt.FontMetrics;
53 import java.awt.Graphics;
54 import java.awt.GridLayout;
55 import java.awt.Point;
56 import java.awt.Rectangle;
57 import java.awt.Toolkit;
58 import java.awt.Window;
59 import java.awt.datatransfer.Clipboard;
60 import java.awt.datatransfer.ClipboardOwner;
61 import java.awt.datatransfer.DataFlavor;
62 import java.awt.datatransfer.Transferable;
63 import java.awt.dnd.DnDConstants;
64 import java.awt.dnd.DropTargetDragEvent;
65 import java.awt.dnd.DropTargetDropEvent;
66 import java.awt.dnd.DropTargetEvent;
67 import java.awt.dnd.DropTargetListener;
68 import java.awt.event.ActionEvent;
69 import java.awt.event.ActionListener;
70 import java.awt.event.FocusEvent;
71 import java.awt.event.FocusListener;
72 import java.awt.event.KeyEvent;
73 import java.awt.event.MouseAdapter;
74 import java.awt.event.MouseEvent;
75 import java.awt.event.WindowAdapter;
76 import java.awt.event.WindowEvent;
77 import java.beans.PropertyChangeEvent;
78 import java.beans.PropertyChangeListener;
79 import java.io.BufferedInputStream;
81 import java.io.FileOutputStream;
82 import java.io.IOException;
84 import java.util.ArrayList;
85 import java.util.Hashtable;
86 import java.util.List;
87 import java.util.ListIterator;
88 import java.util.StringTokenizer;
89 import java.util.Vector;
90 import java.util.concurrent.ExecutorService;
91 import java.util.concurrent.Executors;
92 import java.util.concurrent.Semaphore;
94 import javax.swing.AbstractAction;
95 import javax.swing.Box;
96 import javax.swing.BoxLayout;
97 import javax.swing.DesktopManager;
98 import javax.swing.JButton;
99 import javax.swing.JCheckBox;
100 import javax.swing.JComboBox;
101 import javax.swing.JComponent;
102 import javax.swing.JDesktopPane;
103 import javax.swing.JFrame;
104 import javax.swing.JInternalFrame;
105 import javax.swing.JLabel;
106 import javax.swing.JMenuItem;
107 import javax.swing.JPanel;
108 import javax.swing.JPopupMenu;
109 import javax.swing.JProgressBar;
110 import javax.swing.KeyStroke;
111 import javax.swing.SwingUtilities;
112 import javax.swing.event.HyperlinkEvent;
113 import javax.swing.event.HyperlinkEvent.EventType;
114 import javax.swing.event.InternalFrameAdapter;
115 import javax.swing.event.InternalFrameEvent;
116 import javax.swing.event.MenuEvent;
117 import javax.swing.event.MenuListener;
124 * @version $Revision: 1.155 $
126 public class Desktop extends jalview.jbgui.GDesktop
127 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
128 jalview.api.StructureSelectionManagerProvider
130 private static int DEFAULT_MIN_WIDTH = 300;
132 private static int DEFAULT_MIN_HEIGHT = 250;
134 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
136 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
138 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
140 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
143 * news reader - null if it was never started.
145 private BlogReader jvnews = null;
147 private File projectFile;
151 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
153 public void addJalviewPropertyChangeListener(
154 PropertyChangeListener listener)
156 changeSupport.addJalviewPropertyChangeListener(listener);
160 * @param propertyName
162 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
163 * java.beans.PropertyChangeListener)
165 public void addJalviewPropertyChangeListener(String propertyName,
166 PropertyChangeListener listener)
168 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
172 * @param propertyName
174 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
175 * java.beans.PropertyChangeListener)
177 public void removeJalviewPropertyChangeListener(String propertyName,
178 PropertyChangeListener listener)
180 changeSupport.removeJalviewPropertyChangeListener(propertyName,
184 /** Singleton Desktop instance */
185 public static Desktop instance;
187 public static MyDesktopPane desktop;
189 static int openFrameCount = 0;
191 static final int xOffset = 30;
193 static final int yOffset = 30;
195 public static jalview.ws.jws1.Discoverer discoverer;
197 public static Object[] jalviewClipboard;
199 public static boolean internalCopy = false;
201 static int fileLoadingCount = 0;
203 class MyDesktopManager implements DesktopManager
206 private DesktopManager delegate;
208 public MyDesktopManager(DesktopManager delegate)
210 this.delegate = delegate;
214 public void activateFrame(JInternalFrame f)
218 delegate.activateFrame(f);
219 } catch (NullPointerException npe)
221 Point p = getMousePosition();
222 instance.showPasteMenu(p.x, p.y);
227 public void beginDraggingFrame(JComponent f)
229 delegate.beginDraggingFrame(f);
233 public void beginResizingFrame(JComponent f, int direction)
235 delegate.beginResizingFrame(f, direction);
239 public void closeFrame(JInternalFrame f)
241 delegate.closeFrame(f);
245 public void deactivateFrame(JInternalFrame f)
247 delegate.deactivateFrame(f);
251 public void deiconifyFrame(JInternalFrame f)
253 delegate.deiconifyFrame(f);
257 public void dragFrame(JComponent f, int newX, int newY)
263 delegate.dragFrame(f, newX, newY);
267 public void endDraggingFrame(JComponent f)
269 delegate.endDraggingFrame(f);
274 public void endResizingFrame(JComponent f)
276 delegate.endResizingFrame(f);
281 public void iconifyFrame(JInternalFrame f)
283 delegate.iconifyFrame(f);
287 public void maximizeFrame(JInternalFrame f)
289 delegate.maximizeFrame(f);
293 public void minimizeFrame(JInternalFrame f)
295 delegate.minimizeFrame(f);
299 public void openFrame(JInternalFrame f)
301 delegate.openFrame(f);
305 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
312 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
316 public void setBoundsForFrame(JComponent f, int newX, int newY,
317 int newWidth, int newHeight)
319 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
322 // All other methods, simply delegate
327 * Creates a new Desktop object.
332 * A note to implementors. It is ESSENTIAL that any activities that might
333 * block are spawned off as threads rather than waited for during this
337 doVamsasClientCheck();
339 doConfigureStructurePrefs();
340 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
341 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
342 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
344 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
346 desktop = new MyDesktopPane(selmemusage);
347 showMemusage.setSelected(selmemusage);
348 desktop.setBackground(Color.white);
349 getContentPane().setLayout(new BorderLayout());
350 // alternate config - have scrollbars - see notes in JAL-153
351 // JScrollPane sp = new JScrollPane();
352 // sp.getViewport().setView(desktop);
353 // getContentPane().add(sp, BorderLayout.CENTER);
354 getContentPane().add(desktop, BorderLayout.CENTER);
355 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
357 // This line prevents Windows Look&Feel resizing all new windows to maximum
358 // if previous window was maximised
359 desktop.setDesktopManager(
360 new MyDesktopManager(desktop.getDesktopManager()));
362 Rectangle dims = getLastKnownDimensions("");
369 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
370 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
373 jconsole = new Console(this, showjconsole);
374 // add essential build information
376 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
377 + "\n" + "Jalview Installation: "
378 + jalview.bin.Cache.getDefault("INSTALLATION",
380 + "\n" + "Build Date: "
381 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
382 + "\n" + "Java version: "
383 + System.getProperty("java.version") + "\n"
384 + System.getProperty("os.arch") + " "
385 + System.getProperty("os.name") + " "
386 + System.getProperty("os.version"));
388 showConsole(showjconsole);
390 showNews.setVisible(false);
392 experimentalFeatures.setSelected(showExperimental());
394 getIdentifiersOrgData();
398 this.addWindowListener(new WindowAdapter()
401 public void windowClosing(WindowEvent evt)
408 this.addMouseListener(ma = new MouseAdapter()
411 public void mousePressed(MouseEvent evt)
413 if (evt.isPopupTrigger()) // Mac
415 showPasteMenu(evt.getX(), evt.getY());
420 public void mouseReleased(MouseEvent evt)
422 if (evt.isPopupTrigger()) // Windows
424 showPasteMenu(evt.getX(), evt.getY());
428 desktop.addMouseListener(ma);
430 this.addFocusListener(new FocusListener()
434 public void focusLost(FocusEvent e)
436 // TODO Auto-generated method stub
441 public void focusGained(FocusEvent e)
443 Cache.log.debug("Relaying windows after focus gain");
444 // make sure that we sort windows properly after we gain focus
445 instance.relayerWindows();
448 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
449 // Spawn a thread that shows the splashscreen
450 SwingUtilities.invokeLater(new Runnable()
459 // Thread off a new instance of the file chooser - this reduces the time it
460 // takes to open it later on.
461 new Thread(new Runnable()
466 Cache.log.debug("Filechooser init thread started.");
467 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
468 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
470 Cache.log.debug("Filechooser init thread finished.");
473 // Add the service change listener
474 changeSupport.addJalviewPropertyChangeListener("services",
475 new PropertyChangeListener()
479 public void propertyChange(PropertyChangeEvent evt)
481 Cache.log.debug("Firing service changed event for "
482 + evt.getNewValue());
483 JalviewServicesChanged(evt);
490 * Answers true if user preferences to enable experimental features is True
495 public boolean showExperimental()
497 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
498 Boolean.FALSE.toString());
499 return Boolean.valueOf(experimental).booleanValue();
502 public void doConfigureStructurePrefs()
504 // configure services
505 StructureSelectionManager ssm = StructureSelectionManager
506 .getStructureSelectionManager(this);
507 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
509 ssm.setAddTempFacAnnot(jalview.bin.Cache
510 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
511 ssm.setProcessSecondaryStructure(jalview.bin.Cache
512 .getDefault(Preferences.STRUCT_FROM_PDB, true));
513 ssm.setSecStructServices(
514 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
518 ssm.setAddTempFacAnnot(false);
519 ssm.setProcessSecondaryStructure(false);
520 ssm.setSecStructServices(false);
524 public void checkForNews()
526 final Desktop me = this;
527 // Thread off the news reader, in case there are connection problems.
528 addDialogThread(new Runnable()
533 Cache.log.debug("Starting news thread.");
535 jvnews = new BlogReader(me);
536 showNews.setVisible(true);
537 Cache.log.debug("Completed news thread.");
542 public void getIdentifiersOrgData()
544 // Thread off the identifiers fetcher
545 addDialogThread(new Runnable()
550 Cache.log.debug("Downloading data from identifiers.org");
551 UrlDownloadClient client = new UrlDownloadClient();
554 client.download(IdOrgSettings.getUrl(),
555 IdOrgSettings.getDownloadLocation());
556 } catch (IOException e)
558 Cache.log.debug("Exception downloading identifiers.org data"
566 protected void showNews_actionPerformed(ActionEvent e)
568 showNews(showNews.isSelected());
571 void showNews(boolean visible)
574 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
575 showNews.setSelected(visible);
576 if (visible && !jvnews.isVisible())
578 new Thread(new Runnable()
583 long now = System.currentTimeMillis();
584 Desktop.instance.setProgressBar(
585 MessageManager.getString("status.refreshing_news"),
587 jvnews.refreshNews();
588 Desktop.instance.setProgressBar(null, now);
597 * recover the last known dimensions for a jalview window
600 * - empty string is desktop, all other windows have unique prefix
601 * @return null or last known dimensions scaled to current geometry (if last
602 * window geom was known)
604 Rectangle getLastKnownDimensions(String windowName)
606 // TODO: lock aspect ratio for scaling desktop Bug #0058199
607 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
608 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
609 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
610 String width = jalview.bin.Cache
611 .getProperty(windowName + "SCREEN_WIDTH");
612 String height = jalview.bin.Cache
613 .getProperty(windowName + "SCREEN_HEIGHT");
614 if ((x != null) && (y != null) && (width != null) && (height != null))
616 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
617 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
618 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
620 // attempt #1 - try to cope with change in screen geometry - this
621 // version doesn't preserve original jv aspect ratio.
622 // take ratio of current screen size vs original screen size.
623 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
624 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
625 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
626 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
627 // rescale the bounds depending upon the current screen geometry.
628 ix = (int) (ix * sw);
629 iw = (int) (iw * sw);
630 iy = (int) (iy * sh);
631 ih = (int) (ih * sh);
632 while (ix >= screenSize.width)
634 jalview.bin.Cache.log.debug(
635 "Window geometry location recall error: shifting horizontal to within screenbounds.");
636 ix -= screenSize.width;
638 while (iy >= screenSize.height)
640 jalview.bin.Cache.log.debug(
641 "Window geometry location recall error: shifting vertical to within screenbounds.");
642 iy -= screenSize.height;
644 jalview.bin.Cache.log.debug(
645 "Got last known dimensions for " + windowName + ": x:" + ix
646 + " y:" + iy + " width:" + iw + " height:" + ih);
648 // return dimensions for new instance
649 return new Rectangle(ix, iy, iw, ih);
654 private void doVamsasClientCheck()
656 if (jalview.bin.Cache.vamsasJarsPresent())
658 setupVamsasDisconnectedGui();
659 VamsasMenu.setVisible(true);
660 final Desktop us = this;
661 VamsasMenu.addMenuListener(new MenuListener()
663 // this listener remembers when the menu was first selected, and
664 // doesn't rebuild the session list until it has been cleared and
666 boolean refresh = true;
669 public void menuCanceled(MenuEvent e)
675 public void menuDeselected(MenuEvent e)
681 public void menuSelected(MenuEvent e)
685 us.buildVamsasStMenu();
690 vamsasStart.setVisible(true);
694 void showPasteMenu(int x, int y)
696 JPopupMenu popup = new JPopupMenu();
697 JMenuItem item = new JMenuItem(
698 MessageManager.getString("label.paste_new_window"));
699 item.addActionListener(new ActionListener()
702 public void actionPerformed(ActionEvent evt)
709 popup.show(this, x, y);
716 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
717 Transferable contents = c.getContents(this);
719 if (contents != null)
721 String file = (String) contents
722 .getTransferData(DataFlavor.stringFlavor);
724 FileFormatI format = new IdentifyFile().identify(file,
725 DataSourceType.PASTE);
727 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
730 } catch (Exception ex)
733 "Unable to paste alignment from system clipboard:\n" + ex);
738 * Adds and opens the given frame to the desktop
749 public static synchronized void addInternalFrame(
750 final JInternalFrame frame, String title, int w, int h)
752 addInternalFrame(frame, title, true, w, h, true, false);
756 * Add an internal frame to the Jalview desktop
763 * When true, display frame immediately, otherwise, caller must call
764 * setVisible themselves.
770 public static synchronized void addInternalFrame(
771 final JInternalFrame frame, String title, boolean makeVisible,
774 addInternalFrame(frame, title, makeVisible, w, h, true, false);
778 * Add an internal frame to the Jalview desktop and make it visible
791 public static synchronized void addInternalFrame(
792 final JInternalFrame frame, String title, int w, int h,
795 addInternalFrame(frame, title, true, w, h, resizable, false);
799 * Add an internal frame to the Jalview desktop
806 * When true, display frame immediately, otherwise, caller must call
807 * setVisible themselves.
814 * @param ignoreMinSize
815 * Do not set the default minimum size for frame
817 public static synchronized void addInternalFrame(
818 final JInternalFrame frame, String title, boolean makeVisible,
819 int w, int h, boolean resizable, boolean ignoreMinSize)
822 // TODO: allow callers to determine X and Y position of frame (eg. via
824 // TODO: consider fixing method to update entries in the window submenu with
825 // the current window title
827 frame.setTitle(title);
828 if (frame.getWidth() < 1 || frame.getHeight() < 1)
832 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
833 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
834 // IF JALVIEW IS RUNNING HEADLESS
835 // ///////////////////////////////////////////////
836 if (instance == null || (System.getProperty("java.awt.headless") != null
837 && System.getProperty("java.awt.headless").equals("true")))
846 frame.setMinimumSize(
847 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
849 // Set default dimension for Alignment Frame window.
850 // The Alignment Frame window could be added from a number of places,
852 // I did this here in order not to miss out on any Alignment frame.
853 if (frame instanceof AlignFrame)
855 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
856 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
860 frame.setVisible(makeVisible);
861 frame.setClosable(true);
862 frame.setResizable(resizable);
863 frame.setMaximizable(resizable);
864 frame.setIconifiable(resizable);
866 if (frame.getX() < 1 && frame.getY() < 1)
868 frame.setLocation(xOffset * openFrameCount,
869 yOffset * ((openFrameCount - 1) % 10) + yOffset);
873 * add an entry for the new frame in the Window menu
874 * (and remove it when the frame is closed)
876 final JMenuItem menuItem = new JMenuItem(title);
877 frame.addInternalFrameListener(new InternalFrameAdapter()
880 public void internalFrameActivated(InternalFrameEvent evt)
882 JInternalFrame itf = desktop.getSelectedFrame();
890 public void internalFrameClosed(InternalFrameEvent evt)
892 PaintRefresher.RemoveComponent(frame);
895 * defensive check to prevent frames being
896 * added half off the window
898 if (openFrameCount > 0)
904 * ensure no reference to alignFrame retained by menu item listener
906 if (menuItem.getActionListeners().length > 0)
908 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
910 windowMenu.remove(menuItem);
911 JInternalFrame itf = desktop.getSelectedFrame();
915 if (itf instanceof AlignFrame)
917 Jalview.setCurrentAlignFrame((AlignFrame) itf);
924 menuItem.addActionListener(new ActionListener()
927 public void actionPerformed(ActionEvent e)
931 frame.setSelected(true);
932 frame.setIcon(false);
933 } catch (java.beans.PropertyVetoException ex)
942 windowMenu.add(menuItem);
947 frame.setSelected(true);
948 frame.requestFocus();
949 } catch (java.beans.PropertyVetoException ve)
951 } catch (java.lang.ClassCastException cex)
954 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
960 public void lostOwnership(Clipboard clipboard, Transferable contents)
964 Desktop.jalviewClipboard = null;
967 internalCopy = false;
971 public void dragEnter(DropTargetDragEvent evt)
976 public void dragExit(DropTargetEvent evt)
981 public void dragOver(DropTargetDragEvent evt)
986 public void dropActionChanged(DropTargetDragEvent evt)
997 public void drop(DropTargetDropEvent evt)
999 boolean success = true;
1000 // JAL-1552 - acceptDrop required before getTransferable call for
1001 // Java's Transferable for native dnd
1002 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
1003 Transferable t = evt.getTransferable();
1004 List<String> files = new ArrayList<>();
1005 List<DataSourceType> protocols = new ArrayList<>();
1009 Desktop.transferFromDropTarget(files, protocols, evt, t);
1010 } catch (Exception e)
1012 e.printStackTrace();
1020 for (int i = 0; i < files.size(); i++)
1022 String file = files.get(i).toString();
1023 DataSourceType protocol = (protocols == null)
1024 ? DataSourceType.FILE
1026 FileFormatI format = null;
1028 if (file.endsWith(".jar"))
1030 format = FileFormat.Jalview;
1035 format = new IdentifyFile().identify(file, protocol);
1038 new FileLoader().LoadFile(file, protocol, format);
1041 } catch (Exception ex)
1046 evt.dropComplete(success); // need this to ensure input focus is properly
1047 // transfered to any new windows created
1057 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1059 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1060 JalviewFileChooser chooser = JalviewFileChooser
1061 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1063 chooser.setFileView(new JalviewFileView());
1064 chooser.setDialogTitle(
1065 MessageManager.getString("label.open_local_file"));
1066 chooser.setToolTipText(MessageManager.getString("action.open"));
1068 int value = chooser.showOpenDialog(this);
1070 if (value == JalviewFileChooser.APPROVE_OPTION)
1072 String choice = chooser.getSelectedFile().getPath();
1073 Cache.setProperty("LAST_DIRECTORY",
1074 chooser.getSelectedFile().getParent());
1076 FileFormatI format = chooser.getSelectedFormat();
1079 * Call IdentifyFile to verify the file contains what its extension implies.
1080 * Skip this step for dynamically added file formats, because
1081 * IdentifyFile does not know how to recognise them.
1083 if (FileFormats.getInstance().isIdentifiable(format))
1087 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1088 } catch (FileFormatException e)
1090 // format = null; //??
1094 if (viewport != null)
1096 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1101 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1113 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1115 // This construct allows us to have a wider textfield
1117 JLabel label = new JLabel(
1118 MessageManager.getString("label.input_file_url"));
1119 final JComboBox history = new JComboBox();
1121 JPanel panel = new JPanel(new GridLayout(2, 1));
1124 history.setPreferredSize(new Dimension(400, 20));
1125 history.setEditable(true);
1126 history.addItem("http://www.");
1128 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1132 if (historyItems != null)
1134 st = new StringTokenizer(historyItems, "\t");
1136 while (st.hasMoreTokens())
1138 history.addItem(st.nextElement());
1142 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1143 MessageManager.getString("label.input_alignment_from_url"),
1144 JvOptionPane.OK_CANCEL_OPTION);
1146 if (reply != JvOptionPane.OK_OPTION)
1151 String url = history.getSelectedItem().toString();
1153 if (url.toLowerCase().endsWith(".jar"))
1155 if (viewport != null)
1157 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1158 FileFormat.Jalview);
1162 new FileLoader().LoadFile(url, DataSourceType.URL,
1163 FileFormat.Jalview);
1168 FileFormatI format = null;
1171 format = new IdentifyFile().identify(url, DataSourceType.URL);
1172 } catch (FileFormatException e)
1174 // TODO revise error handling, distinguish between
1175 // URL not found and response not valid
1180 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1181 MessageManager.formatMessage("label.couldnt_locate",
1184 MessageManager.getString("label.url_not_found"),
1185 JvOptionPane.WARNING_MESSAGE);
1190 if (viewport != null)
1192 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1197 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1203 * Opens the CutAndPaste window for the user to paste an alignment in to
1206 * - if not null, the pasted alignment is added to the current
1207 * alignment; if null, to a new alignment window
1210 public void inputTextboxMenuItem_actionPerformed(
1211 AlignmentViewPanel viewPanel)
1213 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1214 cap.setForInput(viewPanel);
1215 Desktop.addInternalFrame(cap,
1216 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1226 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1227 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1229 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1230 screen.height + "");
1231 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1232 getWidth(), getHeight()));
1234 if (jconsole != null)
1236 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1237 jconsole.stopConsole();
1241 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1244 if (dialogExecutor != null)
1246 dialogExecutor.shutdownNow();
1248 closeAll_actionPerformed(null);
1250 if (groovyConsole != null)
1252 // suppress a possible repeat prompt to save script
1253 groovyConsole.setDirty(false);
1254 groovyConsole.exit();
1259 private void storeLastKnownDimensions(String string, Rectangle jc)
1261 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1262 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1263 + " height:" + jc.height);
1265 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1266 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1267 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1268 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1278 public void aboutMenuItem_actionPerformed(ActionEvent e)
1280 // StringBuffer message = getAboutMessage(false);
1281 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1283 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1284 new Thread(new Runnable()
1289 new SplashScreen(true);
1294 public StringBuffer getAboutMessage(boolean shortv)
1296 StringBuffer message = new StringBuffer();
1297 message.append("<html>");
1300 message.append("<h1><strong>Version: "
1301 + jalview.bin.Cache.getProperty("VERSION")
1302 + "</strong></h1>");
1303 message.append("<strong>Last Updated: <em>"
1304 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1305 + "</em></strong>");
1311 message.append("<strong>Version "
1312 + jalview.bin.Cache.getProperty("VERSION")
1313 + "; last updated: "
1314 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1317 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1318 .equals("Checking"))
1320 message.append("<br>...Checking latest version...</br>");
1322 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1323 .equals(jalview.bin.Cache.getProperty("VERSION")))
1325 boolean red = false;
1326 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1327 .indexOf("automated build") == -1)
1330 // Displayed when code version and jnlp version do not match and code
1331 // version is not a development build
1332 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1335 message.append("<br>!! Version "
1336 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1338 + " is available for download from "
1339 + jalview.bin.Cache.getDefault("www.jalview.org",
1340 "http://www.jalview.org")
1344 message.append("</div>");
1347 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1349 "The Jalview Authors (See AUTHORS file for current list)")
1350 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1351 + "<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"
1352 + "<br><br>If you use Jalview, please cite:"
1353 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1354 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1355 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1367 public void documentationMenuItem_actionPerformed(ActionEvent e)
1371 Help.showHelpWindow();
1372 } catch (Exception ex)
1378 public void closeAll_actionPerformed(ActionEvent e)
1380 // TODO show a progress bar while closing?
1381 JInternalFrame[] frames = desktop.getAllFrames();
1382 for (int i = 0; i < frames.length; i++)
1386 frames[i].setClosed(true);
1387 } catch (java.beans.PropertyVetoException ex)
1391 Jalview.setCurrentAlignFrame(null);
1392 System.out.println("ALL CLOSED");
1393 if (v_client != null)
1395 // TODO clear binding to vamsas document objects on close_all
1399 * reset state of singleton objects as appropriate (clear down session state
1400 * when all windows are closed)
1402 StructureSelectionManager ssm = StructureSelectionManager
1403 .getStructureSelectionManager(this);
1412 public void raiseRelated_actionPerformed(ActionEvent e)
1414 reorderAssociatedWindows(false, false);
1418 public void minimizeAssociated_actionPerformed(ActionEvent e)
1420 reorderAssociatedWindows(true, false);
1423 void closeAssociatedWindows()
1425 reorderAssociatedWindows(false, true);
1431 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1435 protected void garbageCollect_actionPerformed(ActionEvent e)
1437 // We simply collect the garbage
1438 jalview.bin.Cache.log.debug("Collecting garbage...");
1440 jalview.bin.Cache.log.debug("Finished garbage collection.");
1447 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1451 protected void showMemusage_actionPerformed(ActionEvent e)
1453 desktop.showMemoryUsage(showMemusage.isSelected());
1460 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1464 protected void showConsole_actionPerformed(ActionEvent e)
1466 showConsole(showConsole.isSelected());
1469 Console jconsole = null;
1472 * control whether the java console is visible or not
1476 void showConsole(boolean selected)
1478 showConsole.setSelected(selected);
1479 // TODO: decide if we should update properties file
1480 Cache.setProperty("SHOW_JAVA_CONSOLE",
1481 Boolean.valueOf(selected).toString());
1482 jconsole.setVisible(selected);
1485 void reorderAssociatedWindows(boolean minimize, boolean close)
1487 JInternalFrame[] frames = desktop.getAllFrames();
1488 if (frames == null || frames.length < 1)
1493 AlignmentViewport source = null, target = null;
1494 if (frames[0] instanceof AlignFrame)
1496 source = ((AlignFrame) frames[0]).getCurrentView();
1498 else if (frames[0] instanceof TreePanel)
1500 source = ((TreePanel) frames[0]).getViewPort();
1502 else if (frames[0] instanceof PCAPanel)
1504 source = ((PCAPanel) frames[0]).av;
1506 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1508 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1513 for (int i = 0; i < frames.length; i++)
1516 if (frames[i] == null)
1520 if (frames[i] instanceof AlignFrame)
1522 target = ((AlignFrame) frames[i]).getCurrentView();
1524 else if (frames[i] instanceof TreePanel)
1526 target = ((TreePanel) frames[i]).getViewPort();
1528 else if (frames[i] instanceof PCAPanel)
1530 target = ((PCAPanel) frames[i]).av;
1532 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1534 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1537 if (source == target)
1543 frames[i].setClosed(true);
1547 frames[i].setIcon(minimize);
1550 frames[i].toFront();
1554 } catch (java.beans.PropertyVetoException ex)
1569 protected void preferences_actionPerformed(ActionEvent e)
1581 public void saveState_actionPerformed(ActionEvent e)
1583 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1586 chooser.setFileView(new JalviewFileView());
1587 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1589 int value = chooser.showSaveDialog(this);
1591 if (value == JalviewFileChooser.APPROVE_OPTION)
1593 final Desktop me = this;
1594 final java.io.File choice = chooser.getSelectedFile();
1595 setProjectFile(choice);
1597 new Thread(new Runnable()
1602 // TODO: refactor to Jalview desktop session controller action.
1603 setProgressBar(MessageManager.formatMessage(
1604 "label.saving_jalview_project", new Object[]
1605 { choice.getName() }), choice.hashCode());
1606 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1607 choice.getParent());
1608 // TODO catch and handle errors for savestate
1609 // TODO prevent user from messing with the Desktop whilst we're saving
1612 new Jalview2XML().saveState(choice);
1613 } catch (OutOfMemoryError oom)
1616 "Whilst saving current state to " + choice.getName(),
1618 } catch (Exception ex)
1621 "Problems whilst trying to save to " + choice.getName(),
1623 JvOptionPane.showMessageDialog(me,
1624 MessageManager.formatMessage(
1625 "label.error_whilst_saving_current_state_to",
1627 { choice.getName() }),
1628 MessageManager.getString("label.couldnt_save_project"),
1629 JvOptionPane.WARNING_MESSAGE);
1631 setProgressBar(null, choice.hashCode());
1637 private void setProjectFile(File choice)
1639 this.projectFile = choice;
1642 public File getProjectFile()
1644 return this.projectFile;
1654 public void loadState_actionPerformed(ActionEvent e)
1656 JalviewFileChooser chooser = new JalviewFileChooser(
1657 Cache.getProperty("LAST_DIRECTORY"), new String[]
1660 { "Jalview Project", "Jalview Project (old)" },
1662 chooser.setFileView(new JalviewFileView());
1663 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1665 int value = chooser.showOpenDialog(this);
1667 if (value == JalviewFileChooser.APPROVE_OPTION)
1669 final File selectedFile = chooser.getSelectedFile();
1670 setProjectFile(selectedFile);
1671 final String choice = selectedFile.getAbsolutePath();
1672 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1673 new Thread(new Runnable()
1678 setProgressBar(MessageManager.formatMessage(
1679 "label.loading_jalview_project", new Object[]
1680 { choice }), choice.hashCode());
1683 new Jalview2XML().loadJalviewAlign(choice);
1684 } catch (OutOfMemoryError oom)
1686 new OOMWarning("Whilst loading project from " + choice, oom);
1687 } catch (Exception ex)
1690 "Problems whilst loading project from " + choice, ex);
1691 JvOptionPane.showMessageDialog(Desktop.desktop,
1692 MessageManager.formatMessage(
1693 "label.error_whilst_loading_project_from",
1696 MessageManager.getString("label.couldnt_load_project"),
1697 JvOptionPane.WARNING_MESSAGE);
1699 setProgressBar(null, choice.hashCode());
1706 public void inputSequence_actionPerformed(ActionEvent e)
1708 new SequenceFetcher(this);
1711 JPanel progressPanel;
1713 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1715 public void startLoading(final String fileName)
1717 if (fileLoadingCount == 0)
1719 fileLoadingPanels.add(addProgressPanel(MessageManager
1720 .formatMessage("label.loading_file", new Object[]
1726 private JPanel addProgressPanel(String string)
1728 if (progressPanel == null)
1730 progressPanel = new JPanel(new GridLayout(1, 1));
1731 totalProgressCount = 0;
1732 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1734 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1735 JProgressBar progressBar = new JProgressBar();
1736 progressBar.setIndeterminate(true);
1738 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1740 thisprogress.add(progressBar, BorderLayout.CENTER);
1741 progressPanel.add(thisprogress);
1742 ((GridLayout) progressPanel.getLayout()).setRows(
1743 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1744 ++totalProgressCount;
1745 instance.validate();
1746 return thisprogress;
1749 int totalProgressCount = 0;
1751 private void removeProgressPanel(JPanel progbar)
1753 if (progressPanel != null)
1755 synchronized (progressPanel)
1757 progressPanel.remove(progbar);
1758 GridLayout gl = (GridLayout) progressPanel.getLayout();
1759 gl.setRows(gl.getRows() - 1);
1760 if (--totalProgressCount < 1)
1762 this.getContentPane().remove(progressPanel);
1763 progressPanel = null;
1770 public void stopLoading()
1773 if (fileLoadingCount < 1)
1775 while (fileLoadingPanels.size() > 0)
1777 removeProgressPanel(fileLoadingPanels.remove(0));
1779 fileLoadingPanels.clear();
1780 fileLoadingCount = 0;
1785 public static int getViewCount(String alignmentId)
1787 AlignmentViewport[] aps = getViewports(alignmentId);
1788 return (aps == null) ? 0 : aps.length;
1793 * @param alignmentId
1794 * - if null, all sets are returned
1795 * @return all AlignmentPanels concerning the alignmentId sequence set
1797 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1799 if (Desktop.desktop == null)
1801 // no frames created and in headless mode
1802 // TODO: verify that frames are recoverable when in headless mode
1805 List<AlignmentPanel> aps = new ArrayList<>();
1806 AlignFrame[] frames = getAlignFrames();
1811 for (AlignFrame af : frames)
1813 for (AlignmentPanel ap : af.alignPanels)
1815 if (alignmentId == null
1816 || alignmentId.equals(ap.av.getSequenceSetId()))
1822 if (aps.size() == 0)
1826 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1831 * get all the viewports on an alignment.
1833 * @param sequenceSetId
1834 * unique alignment id (may be null - all viewports returned in that
1836 * @return all viewports on the alignment bound to sequenceSetId
1838 public static AlignmentViewport[] getViewports(String sequenceSetId)
1840 List<AlignmentViewport> viewp = new ArrayList<>();
1841 if (desktop != null)
1843 AlignFrame[] frames = Desktop.getAlignFrames();
1845 for (AlignFrame afr : frames)
1847 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1848 .equals(sequenceSetId))
1850 if (afr.alignPanels != null)
1852 for (AlignmentPanel ap : afr.alignPanels)
1854 if (sequenceSetId == null
1855 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1863 viewp.add(afr.getViewport());
1867 if (viewp.size() > 0)
1869 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1876 * Explode the views in the given frame into separate AlignFrame
1880 public static void explodeViews(AlignFrame af)
1882 int size = af.alignPanels.size();
1888 for (int i = 0; i < size; i++)
1890 AlignmentPanel ap = af.alignPanels.get(i);
1891 AlignFrame newaf = new AlignFrame(ap);
1894 * Restore the view's last exploded frame geometry if known. Multiple
1895 * views from one exploded frame share and restore the same (frame)
1896 * position and size.
1898 Rectangle geometry = ap.av.getExplodedGeometry();
1899 if (geometry != null)
1901 newaf.setBounds(geometry);
1904 ap.av.setGatherViewsHere(false);
1906 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1907 AlignFrame.DEFAULT_HEIGHT);
1910 af.alignPanels.clear();
1911 af.closeMenuItem_actionPerformed(true);
1916 * Gather expanded views (separate AlignFrame's) with the same sequence set
1917 * identifier back in to this frame as additional views, and close the
1918 * expanded views. Note the expanded frames may themselves have multiple
1919 * views. We take the lot.
1923 public void gatherViews(AlignFrame source)
1925 source.viewport.setGatherViewsHere(true);
1926 source.viewport.setExplodedGeometry(source.getBounds());
1927 JInternalFrame[] frames = desktop.getAllFrames();
1928 String viewId = source.viewport.getSequenceSetId();
1930 for (int t = 0; t < frames.length; t++)
1932 if (frames[t] instanceof AlignFrame && frames[t] != source)
1934 AlignFrame af = (AlignFrame) frames[t];
1935 boolean gatherThis = false;
1936 for (int a = 0; a < af.alignPanels.size(); a++)
1938 AlignmentPanel ap = af.alignPanels.get(a);
1939 if (viewId.equals(ap.av.getSequenceSetId()))
1942 ap.av.setGatherViewsHere(false);
1943 ap.av.setExplodedGeometry(af.getBounds());
1944 source.addAlignmentPanel(ap, false);
1950 af.alignPanels.clear();
1951 af.closeMenuItem_actionPerformed(true);
1958 jalview.gui.VamsasApplication v_client = null;
1961 public void vamsasImport_actionPerformed(ActionEvent e)
1963 if (v_client == null)
1965 // Load and try to start a session.
1966 JalviewFileChooser chooser = new JalviewFileChooser(
1967 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1969 chooser.setFileView(new JalviewFileView());
1970 chooser.setDialogTitle(
1971 MessageManager.getString("label.open_saved_vamsas_session"));
1972 chooser.setToolTipText(MessageManager.getString(
1973 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1975 int value = chooser.showOpenDialog(this);
1977 if (value == JalviewFileChooser.APPROVE_OPTION)
1979 String fle = chooser.getSelectedFile().toString();
1980 if (!vamsasImport(chooser.getSelectedFile()))
1982 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1983 MessageManager.formatMessage(
1984 "label.couldnt_import_as_vamsas_session",
1988 .getString("label.vamsas_document_import_failed"),
1989 JvOptionPane.ERROR_MESSAGE);
1995 jalview.bin.Cache.log.error(
1996 "Implementation error - load session from a running session is not supported.");
2001 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2004 * @return true if import was a success and a session was started.
2006 public boolean vamsasImport(URL url)
2008 // TODO: create progress bar
2009 if (v_client != null)
2012 jalview.bin.Cache.log.error(
2013 "Implementation error - load session from a running session is not supported.");
2019 // copy the URL content to a temporary local file
2020 // TODO: be a bit cleverer here with nio (?!)
2021 File file = File.createTempFile("vdocfromurl", ".vdj");
2022 FileOutputStream fos = new FileOutputStream(file);
2023 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2024 byte[] buffer = new byte[2048];
2026 while ((ln = bis.read(buffer)) > -1)
2028 fos.write(buffer, 0, ln);
2032 v_client = new jalview.gui.VamsasApplication(this, file,
2033 url.toExternalForm());
2034 } catch (Exception ex)
2036 jalview.bin.Cache.log.error(
2037 "Failed to create new vamsas session from contents of URL "
2042 setupVamsasConnectedGui();
2043 v_client.initial_update(); // TODO: thread ?
2044 return v_client.inSession();
2048 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2051 * @return true if import was a success and a session was started.
2053 public boolean vamsasImport(File file)
2055 if (v_client != null)
2058 jalview.bin.Cache.log.error(
2059 "Implementation error - load session from a running session is not supported.");
2063 setProgressBar(MessageManager.formatMessage(
2064 "status.importing_vamsas_session_from", new Object[]
2065 { file.getName() }), file.hashCode());
2068 v_client = new jalview.gui.VamsasApplication(this, file, null);
2069 } catch (Exception ex)
2071 setProgressBar(MessageManager.formatMessage(
2072 "status.importing_vamsas_session_from", new Object[]
2073 { file.getName() }), file.hashCode());
2074 jalview.bin.Cache.log.error(
2075 "New vamsas session from existing session file failed:", ex);
2078 setupVamsasConnectedGui();
2079 v_client.initial_update(); // TODO: thread ?
2080 setProgressBar(MessageManager.formatMessage(
2081 "status.importing_vamsas_session_from", new Object[]
2082 { file.getName() }), file.hashCode());
2083 return v_client.inSession();
2086 public boolean joinVamsasSession(String mysesid)
2088 if (v_client != null)
2090 throw new Error(MessageManager
2091 .getString("error.try_join_vamsas_session_another"));
2093 if (mysesid == null)
2096 MessageManager.getString("error.invalid_vamsas_session_id"));
2098 v_client = new VamsasApplication(this, mysesid);
2099 setupVamsasConnectedGui();
2100 v_client.initial_update();
2101 return (v_client.inSession());
2105 public void vamsasStart_actionPerformed(ActionEvent e)
2107 if (v_client == null)
2110 // we just start a default session for moment.
2112 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2113 * getProperty("LAST_DIRECTORY"));
2115 * chooser.setFileView(new JalviewFileView());
2116 * chooser.setDialogTitle("Load Vamsas file");
2117 * chooser.setToolTipText("Import");
2119 * int value = chooser.showOpenDialog(this);
2121 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2122 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2124 v_client = new VamsasApplication(this);
2125 setupVamsasConnectedGui();
2126 v_client.initial_update(); // TODO: thread ?
2130 // store current data in session.
2131 v_client.push_update(); // TODO: thread
2135 protected void setupVamsasConnectedGui()
2137 vamsasStart.setText(MessageManager.getString("label.session_update"));
2138 vamsasSave.setVisible(true);
2139 vamsasStop.setVisible(true);
2140 vamsasImport.setVisible(false); // Document import to existing session is
2141 // not possible for vamsas-client-1.0.
2144 protected void setupVamsasDisconnectedGui()
2146 vamsasSave.setVisible(false);
2147 vamsasStop.setVisible(false);
2148 vamsasImport.setVisible(true);
2150 .setText(MessageManager.getString("label.new_vamsas_session"));
2154 public void vamsasStop_actionPerformed(ActionEvent e)
2156 if (v_client != null)
2158 v_client.end_session();
2160 setupVamsasDisconnectedGui();
2164 protected void buildVamsasStMenu()
2166 if (v_client == null)
2168 String[] sess = null;
2171 sess = VamsasApplication.getSessionList();
2172 } catch (Exception e)
2174 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2180 jalview.bin.Cache.log.debug(
2181 "Got current sessions list: " + sess.length + " entries.");
2182 VamsasStMenu.removeAll();
2183 for (int i = 0; i < sess.length; i++)
2185 JMenuItem sessit = new JMenuItem();
2186 sessit.setText(sess[i]);
2187 sessit.setToolTipText(MessageManager
2188 .formatMessage("label.connect_to_session", new Object[]
2190 final Desktop dsktp = this;
2191 final String mysesid = sess[i];
2192 sessit.addActionListener(new ActionListener()
2196 public void actionPerformed(ActionEvent e)
2198 if (dsktp.v_client == null)
2200 Thread rthr = new Thread(new Runnable()
2206 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2207 dsktp.setupVamsasConnectedGui();
2208 dsktp.v_client.initial_update();
2216 VamsasStMenu.add(sessit);
2218 // don't show an empty menu.
2219 VamsasStMenu.setVisible(sess.length > 0);
2224 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2225 VamsasStMenu.removeAll();
2226 VamsasStMenu.setVisible(false);
2231 // Not interested in the content. Just hide ourselves.
2232 VamsasStMenu.setVisible(false);
2237 public void vamsasSave_actionPerformed(ActionEvent e)
2239 if (v_client != null)
2241 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2242 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2245 chooser.setFileView(new JalviewFileView());
2246 chooser.setDialogTitle(MessageManager
2247 .getString("label.save_vamsas_document_archive"));
2249 int value = chooser.showSaveDialog(this);
2251 if (value == JalviewFileChooser.APPROVE_OPTION)
2253 java.io.File choice = chooser.getSelectedFile();
2254 JPanel progpanel = addProgressPanel(MessageManager
2255 .formatMessage("label.saving_vamsas_doc", new Object[]
2256 { choice.getName() }));
2257 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2258 String warnmsg = null;
2259 String warnttl = null;
2262 v_client.vclient.storeDocument(choice);
2265 warnttl = "Serious Problem saving Vamsas Document";
2266 warnmsg = ex.toString();
2267 jalview.bin.Cache.log
2268 .error("Error Whilst saving document to " + choice, ex);
2270 } catch (Exception ex)
2272 warnttl = "Problem saving Vamsas Document.";
2273 warnmsg = ex.toString();
2274 jalview.bin.Cache.log.warn(
2275 "Exception Whilst saving document to " + choice, ex);
2278 removeProgressPanel(progpanel);
2279 if (warnmsg != null)
2281 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2283 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2289 JPanel vamUpdate = null;
2292 * hide vamsas user gui bits when a vamsas document event is being handled.
2295 * true to hide gui, false to reveal gui
2297 public void setVamsasUpdate(boolean b)
2299 Cache.log.debug("Setting gui for Vamsas update "
2300 + (b ? "in progress" : "finished"));
2302 if (vamUpdate != null)
2304 this.removeProgressPanel(vamUpdate);
2308 vamUpdate = this.addProgressPanel(
2309 MessageManager.getString("label.updating_vamsas_session"));
2311 vamsasStart.setVisible(!b);
2312 vamsasStop.setVisible(!b);
2313 vamsasSave.setVisible(!b);
2316 public JInternalFrame[] getAllFrames()
2318 return desktop.getAllFrames();
2322 * Checks the given url to see if it gives a response indicating that the user
2323 * should be informed of a new questionnaire.
2327 public void checkForQuestionnaire(String url)
2329 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2330 // javax.swing.SwingUtilities.invokeLater(jvq);
2331 new Thread(jvq).start();
2334 public void checkURLLinks()
2336 // Thread off the URL link checker
2337 addDialogThread(new Runnable()
2342 if (Cache.getDefault("CHECKURLLINKS", true))
2344 // check what the actual links are - if it's just the default don't
2345 // bother with the warning
2346 List<String> links = Preferences.sequenceUrlLinks
2349 // only need to check links if there is one with a
2350 // SEQUENCE_ID which is not the default EMBL_EBI link
2351 ListIterator<String> li = links.listIterator();
2352 boolean check = false;
2353 List<JLabel> urls = new ArrayList<>();
2354 while (li.hasNext())
2356 String link = li.next();
2357 if (link.contains(SEQUENCE_ID)
2358 && !link.equals(UrlConstants.DEFAULT_STRING))
2361 int barPos = link.indexOf("|");
2362 String urlMsg = barPos == -1 ? link
2363 : link.substring(0, barPos) + ": "
2364 + link.substring(barPos + 1);
2365 urls.add(new JLabel(urlMsg));
2373 // ask user to check in case URL links use old style tokens
2374 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2375 JPanel msgPanel = new JPanel();
2376 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2377 msgPanel.add(Box.createVerticalGlue());
2378 JLabel msg = new JLabel(MessageManager
2379 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2380 JLabel msg2 = new JLabel(MessageManager
2381 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2383 for (JLabel url : urls)
2389 final JCheckBox jcb = new JCheckBox(
2390 MessageManager.getString("label.do_not_display_again"));
2391 jcb.addActionListener(new ActionListener()
2394 public void actionPerformed(ActionEvent e)
2396 // update Cache settings for "don't show this again"
2397 boolean showWarningAgain = !jcb.isSelected();
2398 Cache.setProperty("CHECKURLLINKS",
2399 Boolean.valueOf(showWarningAgain).toString());
2404 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2406 .getString("label.SEQUENCE_ID_no_longer_used"),
2407 JvOptionPane.WARNING_MESSAGE);
2414 * Proxy class for JDesktopPane which optionally displays the current memory
2415 * usage and highlights the desktop area with a red bar if free memory runs
2420 public class MyDesktopPane extends JDesktopPane implements Runnable
2423 private static final float ONE_MB = 1048576f;
2425 boolean showMemoryUsage = false;
2429 java.text.NumberFormat df;
2431 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2434 public MyDesktopPane(boolean showMemoryUsage)
2436 showMemoryUsage(showMemoryUsage);
2439 public void showMemoryUsage(boolean showMemory)
2441 this.showMemoryUsage = showMemory;
2444 Thread worker = new Thread(this);
2450 public boolean isShowMemoryUsage()
2452 return showMemoryUsage;
2458 df = java.text.NumberFormat.getNumberInstance();
2459 df.setMaximumFractionDigits(2);
2460 runtime = Runtime.getRuntime();
2462 while (showMemoryUsage)
2466 maxMemory = runtime.maxMemory() / ONE_MB;
2467 allocatedMemory = runtime.totalMemory() / ONE_MB;
2468 freeMemory = runtime.freeMemory() / ONE_MB;
2469 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2471 percentUsage = (totalFreeMemory / maxMemory) * 100;
2473 // if (percentUsage < 20)
2475 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2477 // instance.set.setBorder(border1);
2480 // sleep after showing usage
2482 } catch (Exception ex)
2484 ex.printStackTrace();
2490 public void paintComponent(Graphics g)
2492 if (showMemoryUsage && g != null && df != null)
2494 if (percentUsage < 20)
2496 g.setColor(Color.red);
2498 FontMetrics fm = g.getFontMetrics();
2501 g.drawString(MessageManager.formatMessage("label.memory_stats",
2503 { df.format(totalFreeMemory), df.format(maxMemory),
2504 df.format(percentUsage) }),
2505 10, getHeight() - fm.getHeight());
2512 * fixes stacking order after a modal dialog to ensure windows that should be
2513 * on top actually are
2515 public void relayerWindows()
2521 * Accessor method to quickly get all the AlignmentFrames loaded.
2523 * @return an array of AlignFrame, or null if none found
2525 public static AlignFrame[] getAlignFrames()
2527 if (Jalview.isHeadlessMode())
2529 // Desktop.desktop is null in headless mode
2530 return new AlignFrame[] { Jalview.currentAlignFrame };
2533 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2539 List<AlignFrame> avp = new ArrayList<>();
2541 for (int i = frames.length - 1; i > -1; i--)
2543 if (frames[i] instanceof AlignFrame)
2545 avp.add((AlignFrame) frames[i]);
2547 else if (frames[i] instanceof SplitFrame)
2550 * Also check for a split frame containing an AlignFrame
2552 GSplitFrame sf = (GSplitFrame) frames[i];
2553 if (sf.getTopFrame() instanceof AlignFrame)
2555 avp.add((AlignFrame) sf.getTopFrame());
2557 if (sf.getBottomFrame() instanceof AlignFrame)
2559 avp.add((AlignFrame) sf.getBottomFrame());
2563 if (avp.size() == 0)
2567 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2572 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2576 public GStructureViewer[] getJmols()
2578 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2584 List<GStructureViewer> avp = new ArrayList<>();
2586 for (int i = frames.length - 1; i > -1; i--)
2588 if (frames[i] instanceof AppJmol)
2590 GStructureViewer af = (GStructureViewer) frames[i];
2594 if (avp.size() == 0)
2598 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2603 * Add Groovy Support to Jalview
2606 public void groovyShell_actionPerformed()
2610 openGroovyConsole();
2611 } catch (Exception ex)
2613 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2614 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2616 MessageManager.getString("label.couldnt_create_groovy_shell"),
2617 MessageManager.getString("label.groovy_support_failed"),
2618 JvOptionPane.ERROR_MESSAGE);
2623 * Open the Groovy console
2625 void openGroovyConsole()
2627 if (groovyConsole == null)
2629 groovyConsole = new groovy.ui.Console();
2630 groovyConsole.setVariable("Jalview", this);
2631 groovyConsole.run();
2634 * We allow only one console at a time, so that AlignFrame menu option
2635 * 'Calculate | Run Groovy script' is unambiguous.
2636 * Disable 'Groovy Console', and enable 'Run script', when the console is
2637 * opened, and the reverse when it is closed
2639 Window window = (Window) groovyConsole.getFrame();
2640 window.addWindowListener(new WindowAdapter()
2643 public void windowClosed(WindowEvent e)
2646 * rebind CMD-Q from Groovy Console to Jalview Quit
2649 enableExecuteGroovy(false);
2655 * show Groovy console window (after close and reopen)
2657 ((Window) groovyConsole.getFrame()).setVisible(true);
2660 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2661 * and disable opening a second console
2663 enableExecuteGroovy(true);
2667 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2668 * binding when opened
2670 protected void addQuitHandler()
2672 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2673 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2674 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2676 getRootPane().getActionMap().put("Quit", new AbstractAction()
2679 public void actionPerformed(ActionEvent e)
2687 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2690 * true if Groovy console is open
2692 public void enableExecuteGroovy(boolean enabled)
2695 * disable opening a second Groovy console
2696 * (or re-enable when the console is closed)
2698 groovyShell.setEnabled(!enabled);
2700 AlignFrame[] alignFrames = getAlignFrames();
2701 if (alignFrames != null)
2703 for (AlignFrame af : alignFrames)
2705 af.setGroovyEnabled(enabled);
2711 * Progress bars managed by the IProgressIndicator method.
2713 private Hashtable<Long, JPanel> progressBars;
2715 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2720 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2723 public void setProgressBar(String message, long id)
2725 if (progressBars == null)
2727 progressBars = new Hashtable<>();
2728 progressBarHandlers = new Hashtable<>();
2731 if (progressBars.get(new Long(id)) != null)
2733 JPanel panel = progressBars.remove(new Long(id));
2734 if (progressBarHandlers.contains(new Long(id)))
2736 progressBarHandlers.remove(new Long(id));
2738 removeProgressPanel(panel);
2742 progressBars.put(new Long(id), addProgressPanel(message));
2749 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2750 * jalview.gui.IProgressIndicatorHandler)
2753 public void registerHandler(final long id,
2754 final IProgressIndicatorHandler handler)
2756 if (progressBarHandlers == null
2757 || !progressBars.containsKey(new Long(id)))
2759 throw new Error(MessageManager.getString(
2760 "error.call_setprogressbar_before_registering_handler"));
2762 progressBarHandlers.put(new Long(id), handler);
2763 final JPanel progressPanel = progressBars.get(new Long(id));
2764 if (handler.canCancel())
2766 JButton cancel = new JButton(
2767 MessageManager.getString("action.cancel"));
2768 final IProgressIndicator us = this;
2769 cancel.addActionListener(new ActionListener()
2773 public void actionPerformed(ActionEvent e)
2775 handler.cancelActivity(id);
2776 us.setProgressBar(MessageManager
2777 .formatMessage("label.cancelled_params", new Object[]
2778 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2782 progressPanel.add(cancel, BorderLayout.EAST);
2788 * @return true if any progress bars are still active
2791 public boolean operationInProgress()
2793 if (progressBars != null && progressBars.size() > 0)
2801 * This will return the first AlignFrame holding the given viewport instance.
2802 * It will break if there are more than one AlignFrames viewing a particular
2806 * @return alignFrame for viewport
2808 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2810 if (desktop != null)
2812 AlignmentPanel[] aps = getAlignmentPanels(
2813 viewport.getSequenceSetId());
2814 for (int panel = 0; aps != null && panel < aps.length; panel++)
2816 if (aps[panel] != null && aps[panel].av == viewport)
2818 return aps[panel].alignFrame;
2825 public VamsasApplication getVamsasApplication()
2832 * flag set if jalview GUI is being operated programmatically
2834 private boolean inBatchMode = false;
2837 * check if jalview GUI is being operated programmatically
2839 * @return inBatchMode
2841 public boolean isInBatchMode()
2847 * set flag if jalview GUI is being operated programmatically
2849 * @param inBatchMode
2851 public void setInBatchMode(boolean inBatchMode)
2853 this.inBatchMode = inBatchMode;
2856 public void startServiceDiscovery()
2858 startServiceDiscovery(false);
2861 public void startServiceDiscovery(boolean blocking)
2863 boolean alive = true;
2864 Thread t0 = null, t1 = null, t2 = null;
2865 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2868 // todo: changesupport handlers need to be transferred
2869 if (discoverer == null)
2871 discoverer = new jalview.ws.jws1.Discoverer();
2872 // register PCS handler for desktop.
2873 discoverer.addPropertyChangeListener(changeSupport);
2875 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2876 // until we phase out completely
2877 (t0 = new Thread(discoverer)).start();
2880 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2882 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2883 .startDiscoverer(changeSupport);
2887 // TODO: do rest service discovery
2896 } catch (Exception e)
2899 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2900 || (t3 != null && t3.isAlive())
2901 || (t0 != null && t0.isAlive());
2907 * called to check if the service discovery process completed successfully.
2911 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2913 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2915 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2916 .getErrorMessages();
2919 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2921 if (serviceChangedDialog == null)
2923 // only run if we aren't already displaying one of these.
2924 addDialogThread(serviceChangedDialog = new Runnable()
2931 * JalviewDialog jd =new JalviewDialog() {
2933 * @Override protected void cancelPressed() { // TODO
2934 * Auto-generated method stub
2936 * }@Override protected void okPressed() { // TODO
2937 * Auto-generated method stub
2939 * }@Override protected void raiseClosed() { // TODO
2940 * Auto-generated method stub
2942 * } }; jd.initDialogFrame(new
2943 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2944 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2945 * + " or mis-configured HTTP proxy settings.<br/>" +
2946 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2948 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2949 * ), true, true, "Web Service Configuration Problem", 450,
2952 * jd.waitForInput();
2954 JvOptionPane.showConfirmDialog(Desktop.desktop,
2955 new JLabel("<html><table width=\"450\"><tr><td>"
2956 + ermsg + "</td></tr></table>"
2957 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2958 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2959 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2960 + " Tools->Preferences dialog box to change them.</p></html>"),
2961 "Web Service Configuration Problem",
2962 JvOptionPane.DEFAULT_OPTION,
2963 JvOptionPane.ERROR_MESSAGE);
2964 serviceChangedDialog = null;
2973 "Errors reported by JABA discovery service. Check web services preferences.\n"
2980 private Runnable serviceChangedDialog = null;
2983 * start a thread to open a URL in the configured browser. Pops up a warning
2984 * dialog to the user if there is an exception when calling out to the browser
2989 public static void showUrl(final String url)
2991 showUrl(url, Desktop.instance);
2995 * Like showUrl but allows progress handler to be specified
2999 * (null) or object implementing IProgressIndicator
3001 public static void showUrl(final String url,
3002 final IProgressIndicator progress)
3004 new Thread(new Runnable()
3011 if (progress != null)
3013 progress.setProgressBar(MessageManager
3014 .formatMessage("status.opening_params", new Object[]
3015 { url }), this.hashCode());
3017 jalview.util.BrowserLauncher.openURL(url);
3018 } catch (Exception ex)
3020 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3022 .getString("label.web_browser_not_found_unix"),
3023 MessageManager.getString("label.web_browser_not_found"),
3024 JvOptionPane.WARNING_MESSAGE);
3026 ex.printStackTrace();
3028 if (progress != null)
3030 progress.setProgressBar(null, this.hashCode());
3036 public static WsParamSetManager wsparamManager = null;
3038 public static ParamManager getUserParameterStore()
3040 if (wsparamManager == null)
3042 wsparamManager = new WsParamSetManager();
3044 return wsparamManager;
3048 * static hyperlink handler proxy method for use by Jalview's internal windows
3052 public static void hyperlinkUpdate(HyperlinkEvent e)
3054 if (e.getEventType() == EventType.ACTIVATED)
3059 url = e.getURL().toString();
3060 Desktop.showUrl(url);
3061 } catch (Exception x)
3065 if (Cache.log != null)
3067 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3072 "Couldn't handle string " + url + " as a URL.");
3075 // ignore any exceptions due to dud links.
3082 * single thread that handles display of dialogs to user.
3084 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3087 * flag indicating if dialogExecutor should try to acquire a permit
3089 private volatile boolean dialogPause = true;
3094 private java.util.concurrent.Semaphore block = new Semaphore(0);
3096 private static groovy.ui.Console groovyConsole;
3099 * add another dialog thread to the queue
3103 public void addDialogThread(final Runnable prompter)
3105 dialogExecutor.submit(new Runnable()
3115 } catch (InterruptedException x)
3120 if (instance == null)
3126 SwingUtilities.invokeAndWait(prompter);
3127 } catch (Exception q)
3129 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3135 public void startDialogQueue()
3137 // set the flag so we don't pause waiting for another permit and semaphore
3138 // the current task to begin
3139 dialogPause = false;
3144 protected void snapShotWindow_actionPerformed(ActionEvent e)
3148 ImageMaker im = new jalview.util.ImageMaker(
3149 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3150 getHeight(), of = new File("Jalview_snapshot"
3151 + System.currentTimeMillis() + ".eps"),
3152 "View of desktop", null, 0, false);
3155 paintAll(im.getGraphics());
3157 } catch (Exception q)
3159 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3163 Cache.log.info("Successfully written snapshot to file "
3164 + of.getAbsolutePath());
3168 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3169 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3170 * and location last time the view was expanded (if any). However it does not
3171 * remember the split pane divider location - this is set to match the
3172 * 'exploding' frame.
3176 public void explodeViews(SplitFrame sf)
3178 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3179 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3180 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3182 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3184 int viewCount = topPanels.size();
3191 * Processing in reverse order works, forwards order leaves the first panels
3192 * not visible. I don't know why!
3194 for (int i = viewCount - 1; i >= 0; i--)
3197 * Make new top and bottom frames. These take over the respective
3198 * AlignmentPanel objects, including their AlignmentViewports, so the
3199 * cdna/protein relationships between the viewports is carried over to the
3202 * explodedGeometry holds the (x, y) position of the previously exploded
3203 * SplitFrame, and the (width, height) of the AlignFrame component
3205 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3206 AlignFrame newTopFrame = new AlignFrame(topPanel);
3207 newTopFrame.setSize(oldTopFrame.getSize());
3208 newTopFrame.setVisible(true);
3209 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3210 .getExplodedGeometry();
3211 if (geometry != null)
3213 newTopFrame.setSize(geometry.getSize());
3216 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3217 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3218 newBottomFrame.setSize(oldBottomFrame.getSize());
3219 newBottomFrame.setVisible(true);
3220 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3221 .getExplodedGeometry();
3222 if (geometry != null)
3224 newBottomFrame.setSize(geometry.getSize());
3227 topPanel.av.setGatherViewsHere(false);
3228 bottomPanel.av.setGatherViewsHere(false);
3229 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3231 if (geometry != null)
3233 splitFrame.setLocation(geometry.getLocation());
3235 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3239 * Clear references to the panels (now relocated in the new SplitFrames)
3240 * before closing the old SplitFrame.
3243 bottomPanels.clear();
3248 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3249 * back into the given SplitFrame as additional views. Note that the gathered
3250 * frames may themselves have multiple views.
3254 public void gatherViews(GSplitFrame source)
3257 * special handling of explodedGeometry for a view within a SplitFrame: - it
3258 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3259 * height) of the AlignFrame component
3261 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3262 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3263 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3264 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3265 myBottomFrame.viewport
3266 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3267 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3268 myTopFrame.viewport.setGatherViewsHere(true);
3269 myBottomFrame.viewport.setGatherViewsHere(true);
3270 String topViewId = myTopFrame.viewport.getSequenceSetId();
3271 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3273 JInternalFrame[] frames = desktop.getAllFrames();
3274 for (JInternalFrame frame : frames)
3276 if (frame instanceof SplitFrame && frame != source)
3278 SplitFrame sf = (SplitFrame) frame;
3279 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3280 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3281 boolean gatherThis = false;
3282 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3284 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3285 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3286 if (topViewId.equals(topPanel.av.getSequenceSetId())
3287 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3290 topPanel.av.setGatherViewsHere(false);
3291 bottomPanel.av.setGatherViewsHere(false);
3292 topPanel.av.setExplodedGeometry(
3293 new Rectangle(sf.getLocation(), topFrame.getSize()));
3294 bottomPanel.av.setExplodedGeometry(
3295 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3296 myTopFrame.addAlignmentPanel(topPanel, false);
3297 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3303 topFrame.getAlignPanels().clear();
3304 bottomFrame.getAlignPanels().clear();
3311 * The dust settles...give focus to the tab we did this from.
3313 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3316 public static groovy.ui.Console getGroovyConsole()
3318 return groovyConsole;
3321 public static void transferFromDropTarget(List<String> files,
3322 List<DataSourceType> protocols, DropTargetDropEvent evt,
3323 Transferable t) throws Exception
3326 DataFlavor uriListFlavor = new DataFlavor(
3327 "text/uri-list;class=java.lang.String");
3328 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3330 // Works on Windows and MacOSX
3331 Cache.log.debug("Drop handled as javaFileListFlavor");
3332 for (Object file : (List) t
3333 .getTransferData(DataFlavor.javaFileListFlavor))
3335 files.add(((File) file).toString());
3336 protocols.add(DataSourceType.FILE);
3341 // Unix like behaviour
3342 boolean added = false;
3344 if (t.isDataFlavorSupported(uriListFlavor))
3346 Cache.log.debug("Drop handled as uriListFlavor");
3347 // This is used by Unix drag system
3348 data = (String) t.getTransferData(uriListFlavor);
3352 // fallback to text: workaround - on OSX where there's a JVM bug
3353 Cache.log.debug("standard URIListFlavor failed. Trying text");
3354 // try text fallback
3355 data = (String) t.getTransferData(
3356 new DataFlavor("text/plain;class=java.lang.String"));
3357 if (Cache.log.isDebugEnabled())
3359 Cache.log.debug("fallback returned " + data);
3362 while (protocols.size() < files.size())
3364 Cache.log.debug("Adding missing FILE protocol for "
3365 + files.get(protocols.size()));
3366 protocols.add(DataSourceType.FILE);
3368 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3369 data, "\r\n"); st.hasMoreTokens();)
3372 String s = st.nextToken();
3373 if (s.startsWith("#"))
3375 // the line is a comment (as per the RFC 2483)
3378 java.net.URI uri = new java.net.URI(s);
3379 if (uri.getScheme().toLowerCase().startsWith("http"))
3381 protocols.add(DataSourceType.URL);
3382 files.add(uri.toString());
3386 // otherwise preserve old behaviour: catch all for file objects
3387 java.io.File file = new java.io.File(uri);
3388 protocols.add(DataSourceType.FILE);
3389 files.add(file.toString());
3392 if (Cache.log.isDebugEnabled())
3394 if (data == null || !added)
3397 "Couldn't resolve drop data. Here are the supported flavors:");
3398 for (DataFlavor fl : t.getTransferDataFlavors())
3401 "Supported transfer dataflavor: " + fl.toString());
3402 Object df = t.getTransferData(fl);
3405 Cache.log.debug("Retrieves: " + df);
3409 Cache.log.debug("Retrieved nothing");
3418 * Sets the Preferences property for experimental features to True or False
3419 * depending on the state of the controlling menu item
3422 protected void showExperimental_actionPerformed(boolean selected)
3424 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));