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.KeyEvent;
72 import java.awt.event.MouseAdapter;
73 import java.awt.event.MouseEvent;
74 import java.awt.event.WindowAdapter;
75 import java.awt.event.WindowEvent;
76 import java.beans.PropertyChangeEvent;
77 import java.beans.PropertyChangeListener;
78 import java.io.BufferedInputStream;
80 import java.io.FileOutputStream;
81 import java.io.IOException;
83 import java.util.ArrayList;
84 import java.util.Hashtable;
85 import java.util.List;
86 import java.util.ListIterator;
87 import java.util.StringTokenizer;
88 import java.util.Vector;
89 import java.util.concurrent.ExecutorService;
90 import java.util.concurrent.Executors;
91 import java.util.concurrent.Semaphore;
93 import javax.swing.AbstractAction;
94 import javax.swing.Box;
95 import javax.swing.BoxLayout;
96 import javax.swing.DefaultDesktopManager;
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(
361 (Platform.isWindows() ? new DefaultDesktopManager()
363 ? new AquaInternalFrameManager(
364 desktop.getDesktopManager())
365 : desktop.getDesktopManager())));
367 Rectangle dims = getLastKnownDimensions("");
374 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
375 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
378 jconsole = new Console(this, showjconsole);
379 // add essential build information
381 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
382 + "\n" + "Jalview Installation: "
383 + jalview.bin.Cache.getDefault("INSTALLATION",
385 + "\n" + "Build Date: "
386 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
387 + "\n" + "Java version: "
388 + System.getProperty("java.version") + "\n"
389 + System.getProperty("os.arch") + " "
390 + System.getProperty("os.name") + " "
391 + System.getProperty("os.version"));
393 showConsole(showjconsole);
395 showNews.setVisible(false);
397 experimentalFeatures.setSelected(showExperimental());
399 getIdentifiersOrgData();
403 this.addWindowListener(new WindowAdapter()
406 public void windowClosing(WindowEvent evt)
413 this.addMouseListener(ma = new MouseAdapter()
416 public void mousePressed(MouseEvent evt)
418 if (evt.isPopupTrigger()) // Mac
420 showPasteMenu(evt.getX(), evt.getY());
425 public void mouseReleased(MouseEvent evt)
427 if (evt.isPopupTrigger()) // Windows
429 showPasteMenu(evt.getX(), evt.getY());
433 desktop.addMouseListener(ma);
435 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
436 // Spawn a thread that shows the splashscreen
437 SwingUtilities.invokeLater(new Runnable()
446 // Thread off a new instance of the file chooser - this reduces the time it
447 // takes to open it later on.
448 new Thread(new Runnable()
453 Cache.log.debug("Filechooser init thread started.");
454 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
455 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
457 Cache.log.debug("Filechooser init thread finished.");
460 // Add the service change listener
461 changeSupport.addJalviewPropertyChangeListener("services",
462 new PropertyChangeListener()
466 public void propertyChange(PropertyChangeEvent evt)
468 Cache.log.debug("Firing service changed event for "
469 + evt.getNewValue());
470 JalviewServicesChanged(evt);
477 * Answers true if user preferences to enable experimental features is True
482 public boolean showExperimental()
484 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
485 Boolean.FALSE.toString());
486 return Boolean.valueOf(experimental).booleanValue();
489 public void doConfigureStructurePrefs()
491 // configure services
492 StructureSelectionManager ssm = StructureSelectionManager
493 .getStructureSelectionManager(this);
494 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
496 ssm.setAddTempFacAnnot(jalview.bin.Cache
497 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
498 ssm.setProcessSecondaryStructure(jalview.bin.Cache
499 .getDefault(Preferences.STRUCT_FROM_PDB, true));
500 ssm.setSecStructServices(
501 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
505 ssm.setAddTempFacAnnot(false);
506 ssm.setProcessSecondaryStructure(false);
507 ssm.setSecStructServices(false);
511 public void checkForNews()
513 final Desktop me = this;
514 // Thread off the news reader, in case there are connection problems.
515 addDialogThread(new Runnable()
520 Cache.log.debug("Starting news thread.");
522 jvnews = new BlogReader(me);
523 showNews.setVisible(true);
524 Cache.log.debug("Completed news thread.");
529 public void getIdentifiersOrgData()
531 // Thread off the identifiers fetcher
532 addDialogThread(new Runnable()
537 Cache.log.debug("Downloading data from identifiers.org");
538 UrlDownloadClient client = new UrlDownloadClient();
541 client.download(IdOrgSettings.getUrl(),
542 IdOrgSettings.getDownloadLocation());
543 } catch (IOException e)
545 Cache.log.debug("Exception downloading identifiers.org data"
553 protected void showNews_actionPerformed(ActionEvent e)
555 showNews(showNews.isSelected());
558 void showNews(boolean visible)
561 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
562 showNews.setSelected(visible);
563 if (visible && !jvnews.isVisible())
565 new Thread(new Runnable()
570 long now = System.currentTimeMillis();
571 Desktop.instance.setProgressBar(
572 MessageManager.getString("status.refreshing_news"),
574 jvnews.refreshNews();
575 Desktop.instance.setProgressBar(null, now);
584 * recover the last known dimensions for a jalview window
587 * - empty string is desktop, all other windows have unique prefix
588 * @return null or last known dimensions scaled to current geometry (if last
589 * window geom was known)
591 Rectangle getLastKnownDimensions(String windowName)
593 // TODO: lock aspect ratio for scaling desktop Bug #0058199
594 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
595 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
596 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
597 String width = jalview.bin.Cache
598 .getProperty(windowName + "SCREEN_WIDTH");
599 String height = jalview.bin.Cache
600 .getProperty(windowName + "SCREEN_HEIGHT");
601 if ((x != null) && (y != null) && (width != null) && (height != null))
603 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
604 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
605 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
607 // attempt #1 - try to cope with change in screen geometry - this
608 // version doesn't preserve original jv aspect ratio.
609 // take ratio of current screen size vs original screen size.
610 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
611 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
612 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
613 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
614 // rescale the bounds depending upon the current screen geometry.
615 ix = (int) (ix * sw);
616 iw = (int) (iw * sw);
617 iy = (int) (iy * sh);
618 ih = (int) (ih * sh);
619 while (ix >= screenSize.width)
621 jalview.bin.Cache.log.debug(
622 "Window geometry location recall error: shifting horizontal to within screenbounds.");
623 ix -= screenSize.width;
625 while (iy >= screenSize.height)
627 jalview.bin.Cache.log.debug(
628 "Window geometry location recall error: shifting vertical to within screenbounds.");
629 iy -= screenSize.height;
631 jalview.bin.Cache.log.debug(
632 "Got last known dimensions for " + windowName + ": x:" + ix
633 + " y:" + iy + " width:" + iw + " height:" + ih);
635 // return dimensions for new instance
636 return new Rectangle(ix, iy, iw, ih);
641 private void doVamsasClientCheck()
643 if (jalview.bin.Cache.vamsasJarsPresent())
645 setupVamsasDisconnectedGui();
646 VamsasMenu.setVisible(true);
647 final Desktop us = this;
648 VamsasMenu.addMenuListener(new MenuListener()
650 // this listener remembers when the menu was first selected, and
651 // doesn't rebuild the session list until it has been cleared and
653 boolean refresh = true;
656 public void menuCanceled(MenuEvent e)
662 public void menuDeselected(MenuEvent e)
668 public void menuSelected(MenuEvent e)
672 us.buildVamsasStMenu();
677 vamsasStart.setVisible(true);
681 void showPasteMenu(int x, int y)
683 JPopupMenu popup = new JPopupMenu();
684 JMenuItem item = new JMenuItem(
685 MessageManager.getString("label.paste_new_window"));
686 item.addActionListener(new ActionListener()
689 public void actionPerformed(ActionEvent evt)
696 popup.show(this, x, y);
703 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
704 Transferable contents = c.getContents(this);
706 if (contents != null)
708 String file = (String) contents
709 .getTransferData(DataFlavor.stringFlavor);
711 FileFormatI format = new IdentifyFile().identify(file,
712 DataSourceType.PASTE);
714 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
717 } catch (Exception ex)
720 "Unable to paste alignment from system clipboard:\n" + ex);
725 * Adds and opens the given frame to the desktop
736 public static synchronized void addInternalFrame(
737 final JInternalFrame frame, String title, int w, int h)
739 addInternalFrame(frame, title, true, w, h, true, false);
743 * Add an internal frame to the Jalview desktop
750 * When true, display frame immediately, otherwise, caller must call
751 * setVisible themselves.
757 public static synchronized void addInternalFrame(
758 final JInternalFrame frame, String title, boolean makeVisible,
761 addInternalFrame(frame, title, makeVisible, w, h, true, false);
765 * Add an internal frame to the Jalview desktop and make it visible
778 public static synchronized void addInternalFrame(
779 final JInternalFrame frame, String title, int w, int h,
782 addInternalFrame(frame, title, true, w, h, resizable, false);
786 * Add an internal frame to the Jalview desktop
793 * When true, display frame immediately, otherwise, caller must call
794 * setVisible themselves.
801 * @param ignoreMinSize
802 * Do not set the default minimum size for frame
804 public static synchronized void addInternalFrame(
805 final JInternalFrame frame, String title, boolean makeVisible,
806 int w, int h, boolean resizable, boolean ignoreMinSize)
809 // TODO: allow callers to determine X and Y position of frame (eg. via
811 // TODO: consider fixing method to update entries in the window submenu with
812 // the current window title
814 frame.setTitle(title);
815 if (frame.getWidth() < 1 || frame.getHeight() < 1)
819 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
820 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
821 // IF JALVIEW IS RUNNING HEADLESS
822 // ///////////////////////////////////////////////
823 if (instance == null || (System.getProperty("java.awt.headless") != null
824 && System.getProperty("java.awt.headless").equals("true")))
833 frame.setMinimumSize(
834 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
836 // Set default dimension for Alignment Frame window.
837 // The Alignment Frame window could be added from a number of places,
839 // I did this here in order not to miss out on any Alignment frame.
840 if (frame instanceof AlignFrame)
842 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
843 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
847 frame.setVisible(makeVisible);
848 frame.setClosable(true);
849 frame.setResizable(resizable);
850 frame.setMaximizable(resizable);
851 frame.setIconifiable(resizable);
853 if (frame.getX() < 1 && frame.getY() < 1)
855 frame.setLocation(xOffset * openFrameCount,
856 yOffset * ((openFrameCount - 1) % 10) + yOffset);
860 * add an entry for the new frame in the Window menu
861 * (and remove it when the frame is closed)
863 final JMenuItem menuItem = new JMenuItem(title);
864 frame.addInternalFrameListener(new InternalFrameAdapter()
867 public void internalFrameActivated(InternalFrameEvent evt)
869 JInternalFrame itf = desktop.getSelectedFrame();
872 if (itf instanceof AlignFrame)
874 Jalview.setCurrentAlignFrame((AlignFrame) itf);
882 public void internalFrameClosed(InternalFrameEvent evt)
884 PaintRefresher.RemoveComponent(frame);
887 * defensive check to prevent frames being
888 * added half off the window
890 if (openFrameCount > 0)
896 * ensure no reference to alignFrame retained by menu item listener
898 if (menuItem.getActionListeners().length > 0)
900 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
902 windowMenu.remove(menuItem);
908 menuItem.addActionListener(new ActionListener()
911 public void actionPerformed(ActionEvent e)
915 frame.setSelected(true);
916 frame.setIcon(false);
917 } catch (java.beans.PropertyVetoException ex)
926 windowMenu.add(menuItem);
931 frame.setSelected(true);
932 frame.requestFocus();
933 } catch (java.beans.PropertyVetoException ve)
935 } catch (java.lang.ClassCastException cex)
938 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
944 public void lostOwnership(Clipboard clipboard, Transferable contents)
948 Desktop.jalviewClipboard = null;
951 internalCopy = false;
955 public void dragEnter(DropTargetDragEvent evt)
960 public void dragExit(DropTargetEvent evt)
965 public void dragOver(DropTargetDragEvent evt)
970 public void dropActionChanged(DropTargetDragEvent evt)
981 public void drop(DropTargetDropEvent evt)
983 boolean success = true;
984 // JAL-1552 - acceptDrop required before getTransferable call for
985 // Java's Transferable for native dnd
986 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
987 Transferable t = evt.getTransferable();
988 List<String> files = new ArrayList<>();
989 List<DataSourceType> protocols = new ArrayList<>();
993 Desktop.transferFromDropTarget(files, protocols, evt, t);
994 } catch (Exception e)
1004 for (int i = 0; i < files.size(); i++)
1006 String file = files.get(i).toString();
1007 DataSourceType protocol = (protocols == null)
1008 ? DataSourceType.FILE
1010 FileFormatI format = null;
1012 if (file.endsWith(".jar"))
1014 format = FileFormat.Jalview;
1019 format = new IdentifyFile().identify(file, protocol);
1022 new FileLoader().LoadFile(file, protocol, format);
1025 } catch (Exception ex)
1030 evt.dropComplete(success); // need this to ensure input focus is properly
1031 // transfered to any new windows created
1041 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1043 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1044 JalviewFileChooser chooser = JalviewFileChooser
1045 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1047 chooser.setFileView(new JalviewFileView());
1048 chooser.setDialogTitle(
1049 MessageManager.getString("label.open_local_file"));
1050 chooser.setToolTipText(MessageManager.getString("action.open"));
1052 int value = chooser.showOpenDialog(this);
1054 if (value == JalviewFileChooser.APPROVE_OPTION)
1056 String choice = chooser.getSelectedFile().getPath();
1057 Cache.setProperty("LAST_DIRECTORY",
1058 chooser.getSelectedFile().getParent());
1060 FileFormatI format = chooser.getSelectedFormat();
1063 * Call IdentifyFile to verify the file contains what its extension implies.
1064 * Skip this step for dynamically added file formats, because
1065 * IdentifyFile does not know how to recognise them.
1067 if (FileFormats.getInstance().isIdentifiable(format))
1071 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1072 } catch (FileFormatException e)
1074 // format = null; //??
1078 if (viewport != null)
1080 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1085 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1097 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1099 // This construct allows us to have a wider textfield
1101 JLabel label = new JLabel(
1102 MessageManager.getString("label.input_file_url"));
1103 final JComboBox history = new JComboBox();
1105 JPanel panel = new JPanel(new GridLayout(2, 1));
1108 history.setPreferredSize(new Dimension(400, 20));
1109 history.setEditable(true);
1110 history.addItem("http://www.");
1112 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1116 if (historyItems != null)
1118 st = new StringTokenizer(historyItems, "\t");
1120 while (st.hasMoreTokens())
1122 history.addItem(st.nextElement());
1126 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1127 MessageManager.getString("label.input_alignment_from_url"),
1128 JvOptionPane.OK_CANCEL_OPTION);
1130 if (reply != JvOptionPane.OK_OPTION)
1135 String url = history.getSelectedItem().toString();
1137 if (url.toLowerCase().endsWith(".jar"))
1139 if (viewport != null)
1141 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1142 FileFormat.Jalview);
1146 new FileLoader().LoadFile(url, DataSourceType.URL,
1147 FileFormat.Jalview);
1152 FileFormatI format = null;
1155 format = new IdentifyFile().identify(url, DataSourceType.URL);
1156 } catch (FileFormatException e)
1158 // TODO revise error handling, distinguish between
1159 // URL not found and response not valid
1164 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1165 MessageManager.formatMessage("label.couldnt_locate",
1168 MessageManager.getString("label.url_not_found"),
1169 JvOptionPane.WARNING_MESSAGE);
1174 if (viewport != null)
1176 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1181 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1187 * Opens the CutAndPaste window for the user to paste an alignment in to
1190 * - if not null, the pasted alignment is added to the current
1191 * alignment; if null, to a new alignment window
1194 public void inputTextboxMenuItem_actionPerformed(
1195 AlignmentViewPanel viewPanel)
1197 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1198 cap.setForInput(viewPanel);
1199 Desktop.addInternalFrame(cap,
1200 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1210 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1211 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1213 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1214 screen.height + "");
1215 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1216 getWidth(), getHeight()));
1218 if (jconsole != null)
1220 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1221 jconsole.stopConsole();
1225 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1228 if (dialogExecutor != null)
1230 dialogExecutor.shutdownNow();
1232 closeAll_actionPerformed(null);
1234 if (groovyConsole != null)
1236 // suppress a possible repeat prompt to save script
1237 groovyConsole.setDirty(false);
1238 groovyConsole.exit();
1243 private void storeLastKnownDimensions(String string, Rectangle jc)
1245 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1246 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1247 + " height:" + jc.height);
1249 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1250 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1251 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1252 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1262 public void aboutMenuItem_actionPerformed(ActionEvent e)
1264 // StringBuffer message = getAboutMessage(false);
1265 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1267 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1268 new Thread(new Runnable()
1273 new SplashScreen(true);
1278 public StringBuffer getAboutMessage(boolean shortv)
1280 StringBuffer message = new StringBuffer();
1281 message.append("<html>");
1284 message.append("<h1><strong>Version: "
1285 + jalview.bin.Cache.getProperty("VERSION")
1286 + "</strong></h1>");
1287 message.append("<strong>Last Updated: <em>"
1288 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1289 + "</em></strong>");
1295 message.append("<strong>Version "
1296 + jalview.bin.Cache.getProperty("VERSION")
1297 + "; last updated: "
1298 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1301 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1302 .equals("Checking"))
1304 message.append("<br>...Checking latest version...</br>");
1306 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1307 .equals(jalview.bin.Cache.getProperty("VERSION")))
1309 boolean red = false;
1310 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1311 .indexOf("automated build") == -1)
1314 // Displayed when code version and jnlp version do not match and code
1315 // version is not a development build
1316 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1319 message.append("<br>!! Version "
1320 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1322 + " is available for download from "
1323 + jalview.bin.Cache.getDefault("www.jalview.org",
1324 "http://www.jalview.org")
1328 message.append("</div>");
1331 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1333 "The Jalview Authors (See AUTHORS file for current list)")
1334 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1335 + "<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"
1336 + "<br><br>If you use Jalview, please cite:"
1337 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1338 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1339 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1351 public void documentationMenuItem_actionPerformed(ActionEvent e)
1355 Help.showHelpWindow();
1356 } catch (Exception ex)
1362 public void closeAll_actionPerformed(ActionEvent e)
1364 // TODO show a progress bar while closing?
1365 JInternalFrame[] frames = desktop.getAllFrames();
1366 for (int i = 0; i < frames.length; i++)
1370 frames[i].setClosed(true);
1371 } catch (java.beans.PropertyVetoException ex)
1375 Jalview.setCurrentAlignFrame(null);
1376 System.out.println("ALL CLOSED");
1377 if (v_client != null)
1379 // TODO clear binding to vamsas document objects on close_all
1383 * reset state of singleton objects as appropriate (clear down session state
1384 * when all windows are closed)
1386 StructureSelectionManager ssm = StructureSelectionManager
1387 .getStructureSelectionManager(this);
1396 public void raiseRelated_actionPerformed(ActionEvent e)
1398 reorderAssociatedWindows(false, false);
1402 public void minimizeAssociated_actionPerformed(ActionEvent e)
1404 reorderAssociatedWindows(true, false);
1407 void closeAssociatedWindows()
1409 reorderAssociatedWindows(false, true);
1415 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1419 protected void garbageCollect_actionPerformed(ActionEvent e)
1421 // We simply collect the garbage
1422 jalview.bin.Cache.log.debug("Collecting garbage...");
1424 jalview.bin.Cache.log.debug("Finished garbage collection.");
1431 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1435 protected void showMemusage_actionPerformed(ActionEvent e)
1437 desktop.showMemoryUsage(showMemusage.isSelected());
1444 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1448 protected void showConsole_actionPerformed(ActionEvent e)
1450 showConsole(showConsole.isSelected());
1453 Console jconsole = null;
1456 * control whether the java console is visible or not
1460 void showConsole(boolean selected)
1462 showConsole.setSelected(selected);
1463 // TODO: decide if we should update properties file
1464 Cache.setProperty("SHOW_JAVA_CONSOLE",
1465 Boolean.valueOf(selected).toString());
1466 jconsole.setVisible(selected);
1469 void reorderAssociatedWindows(boolean minimize, boolean close)
1471 JInternalFrame[] frames = desktop.getAllFrames();
1472 if (frames == null || frames.length < 1)
1477 AlignmentViewport source = null, target = null;
1478 if (frames[0] instanceof AlignFrame)
1480 source = ((AlignFrame) frames[0]).getCurrentView();
1482 else if (frames[0] instanceof TreePanel)
1484 source = ((TreePanel) frames[0]).getViewPort();
1486 else if (frames[0] instanceof PCAPanel)
1488 source = ((PCAPanel) frames[0]).av;
1490 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1492 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1497 for (int i = 0; i < frames.length; i++)
1500 if (frames[i] == null)
1504 if (frames[i] instanceof AlignFrame)
1506 target = ((AlignFrame) frames[i]).getCurrentView();
1508 else if (frames[i] instanceof TreePanel)
1510 target = ((TreePanel) frames[i]).getViewPort();
1512 else if (frames[i] instanceof PCAPanel)
1514 target = ((PCAPanel) frames[i]).av;
1516 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1518 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1521 if (source == target)
1527 frames[i].setClosed(true);
1531 frames[i].setIcon(minimize);
1534 frames[i].toFront();
1538 } catch (java.beans.PropertyVetoException ex)
1553 protected void preferences_actionPerformed(ActionEvent e)
1565 public void saveState_actionPerformed(ActionEvent e)
1567 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1570 chooser.setFileView(new JalviewFileView());
1571 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1573 int value = chooser.showSaveDialog(this);
1575 if (value == JalviewFileChooser.APPROVE_OPTION)
1577 final Desktop me = this;
1578 final java.io.File choice = chooser.getSelectedFile();
1579 setProjectFile(choice);
1581 new Thread(new Runnable()
1586 // TODO: refactor to Jalview desktop session controller action.
1587 setProgressBar(MessageManager.formatMessage(
1588 "label.saving_jalview_project", new Object[]
1589 { choice.getName() }), choice.hashCode());
1590 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1591 choice.getParent());
1592 // TODO catch and handle errors for savestate
1593 // TODO prevent user from messing with the Desktop whilst we're saving
1596 new Jalview2XML().saveState(choice);
1597 } catch (OutOfMemoryError oom)
1600 "Whilst saving current state to " + choice.getName(),
1602 } catch (Exception ex)
1605 "Problems whilst trying to save to " + choice.getName(),
1607 JvOptionPane.showMessageDialog(me,
1608 MessageManager.formatMessage(
1609 "label.error_whilst_saving_current_state_to",
1611 { choice.getName() }),
1612 MessageManager.getString("label.couldnt_save_project"),
1613 JvOptionPane.WARNING_MESSAGE);
1615 setProgressBar(null, choice.hashCode());
1621 private void setProjectFile(File choice)
1623 this.projectFile = choice;
1626 public File getProjectFile()
1628 return this.projectFile;
1638 public void loadState_actionPerformed(ActionEvent e)
1640 JalviewFileChooser chooser = new JalviewFileChooser(
1641 Cache.getProperty("LAST_DIRECTORY"), new String[]
1644 { "Jalview Project", "Jalview Project (old)" },
1646 chooser.setFileView(new JalviewFileView());
1647 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1649 int value = chooser.showOpenDialog(this);
1651 if (value == JalviewFileChooser.APPROVE_OPTION)
1653 final File selectedFile = chooser.getSelectedFile();
1654 setProjectFile(selectedFile);
1655 final String choice = selectedFile.getAbsolutePath();
1656 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1657 new Thread(new Runnable()
1662 setProgressBar(MessageManager.formatMessage(
1663 "label.loading_jalview_project", new Object[]
1664 { choice }), choice.hashCode());
1667 new Jalview2XML().loadJalviewAlign(choice);
1668 } catch (OutOfMemoryError oom)
1670 new OOMWarning("Whilst loading project from " + choice, oom);
1671 } catch (Exception ex)
1674 "Problems whilst loading project from " + choice, ex);
1675 JvOptionPane.showMessageDialog(Desktop.desktop,
1676 MessageManager.formatMessage(
1677 "label.error_whilst_loading_project_from",
1680 MessageManager.getString("label.couldnt_load_project"),
1681 JvOptionPane.WARNING_MESSAGE);
1683 setProgressBar(null, choice.hashCode());
1690 public void inputSequence_actionPerformed(ActionEvent e)
1692 new SequenceFetcher(this);
1695 JPanel progressPanel;
1697 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1699 public void startLoading(final String fileName)
1701 if (fileLoadingCount == 0)
1703 fileLoadingPanels.add(addProgressPanel(MessageManager
1704 .formatMessage("label.loading_file", new Object[]
1710 private JPanel addProgressPanel(String string)
1712 if (progressPanel == null)
1714 progressPanel = new JPanel(new GridLayout(1, 1));
1715 totalProgressCount = 0;
1716 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1718 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1719 JProgressBar progressBar = new JProgressBar();
1720 progressBar.setIndeterminate(true);
1722 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1724 thisprogress.add(progressBar, BorderLayout.CENTER);
1725 progressPanel.add(thisprogress);
1726 ((GridLayout) progressPanel.getLayout()).setRows(
1727 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1728 ++totalProgressCount;
1729 instance.validate();
1730 return thisprogress;
1733 int totalProgressCount = 0;
1735 private void removeProgressPanel(JPanel progbar)
1737 if (progressPanel != null)
1739 synchronized (progressPanel)
1741 progressPanel.remove(progbar);
1742 GridLayout gl = (GridLayout) progressPanel.getLayout();
1743 gl.setRows(gl.getRows() - 1);
1744 if (--totalProgressCount < 1)
1746 this.getContentPane().remove(progressPanel);
1747 progressPanel = null;
1754 public void stopLoading()
1757 if (fileLoadingCount < 1)
1759 while (fileLoadingPanels.size() > 0)
1761 removeProgressPanel(fileLoadingPanels.remove(0));
1763 fileLoadingPanels.clear();
1764 fileLoadingCount = 0;
1769 public static int getViewCount(String alignmentId)
1771 AlignmentViewport[] aps = getViewports(alignmentId);
1772 return (aps == null) ? 0 : aps.length;
1777 * @param alignmentId
1778 * - if null, all sets are returned
1779 * @return all AlignmentPanels concerning the alignmentId sequence set
1781 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1783 if (Desktop.desktop == null)
1785 // no frames created and in headless mode
1786 // TODO: verify that frames are recoverable when in headless mode
1789 List<AlignmentPanel> aps = new ArrayList<>();
1790 AlignFrame[] frames = getAlignFrames();
1795 for (AlignFrame af : frames)
1797 for (AlignmentPanel ap : af.alignPanels)
1799 if (alignmentId == null
1800 || alignmentId.equals(ap.av.getSequenceSetId()))
1806 if (aps.size() == 0)
1810 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1815 * get all the viewports on an alignment.
1817 * @param sequenceSetId
1818 * unique alignment id (may be null - all viewports returned in that
1820 * @return all viewports on the alignment bound to sequenceSetId
1822 public static AlignmentViewport[] getViewports(String sequenceSetId)
1824 List<AlignmentViewport> viewp = new ArrayList<>();
1825 if (desktop != null)
1827 AlignFrame[] frames = Desktop.getAlignFrames();
1829 for (AlignFrame afr : frames)
1831 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1832 .equals(sequenceSetId))
1834 if (afr.alignPanels != null)
1836 for (AlignmentPanel ap : afr.alignPanels)
1838 if (sequenceSetId == null
1839 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1847 viewp.add(afr.getViewport());
1851 if (viewp.size() > 0)
1853 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1860 * Explode the views in the given frame into separate AlignFrame
1864 public static void explodeViews(AlignFrame af)
1866 int size = af.alignPanels.size();
1872 for (int i = 0; i < size; i++)
1874 AlignmentPanel ap = af.alignPanels.get(i);
1875 AlignFrame newaf = new AlignFrame(ap);
1878 * Restore the view's last exploded frame geometry if known. Multiple
1879 * views from one exploded frame share and restore the same (frame)
1880 * position and size.
1882 Rectangle geometry = ap.av.getExplodedGeometry();
1883 if (geometry != null)
1885 newaf.setBounds(geometry);
1888 ap.av.setGatherViewsHere(false);
1890 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1891 AlignFrame.DEFAULT_HEIGHT);
1894 af.alignPanels.clear();
1895 af.closeMenuItem_actionPerformed(true);
1900 * Gather expanded views (separate AlignFrame's) with the same sequence set
1901 * identifier back in to this frame as additional views, and close the
1902 * expanded views. Note the expanded frames may themselves have multiple
1903 * views. We take the lot.
1907 public void gatherViews(AlignFrame source)
1909 source.viewport.setGatherViewsHere(true);
1910 source.viewport.setExplodedGeometry(source.getBounds());
1911 JInternalFrame[] frames = desktop.getAllFrames();
1912 String viewId = source.viewport.getSequenceSetId();
1914 for (int t = 0; t < frames.length; t++)
1916 if (frames[t] instanceof AlignFrame && frames[t] != source)
1918 AlignFrame af = (AlignFrame) frames[t];
1919 boolean gatherThis = false;
1920 for (int a = 0; a < af.alignPanels.size(); a++)
1922 AlignmentPanel ap = af.alignPanels.get(a);
1923 if (viewId.equals(ap.av.getSequenceSetId()))
1926 ap.av.setGatherViewsHere(false);
1927 ap.av.setExplodedGeometry(af.getBounds());
1928 source.addAlignmentPanel(ap, false);
1934 af.alignPanels.clear();
1935 af.closeMenuItem_actionPerformed(true);
1942 jalview.gui.VamsasApplication v_client = null;
1945 public void vamsasImport_actionPerformed(ActionEvent e)
1947 if (v_client == null)
1949 // Load and try to start a session.
1950 JalviewFileChooser chooser = new JalviewFileChooser(
1951 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1953 chooser.setFileView(new JalviewFileView());
1954 chooser.setDialogTitle(
1955 MessageManager.getString("label.open_saved_vamsas_session"));
1956 chooser.setToolTipText(MessageManager.getString(
1957 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1959 int value = chooser.showOpenDialog(this);
1961 if (value == JalviewFileChooser.APPROVE_OPTION)
1963 String fle = chooser.getSelectedFile().toString();
1964 if (!vamsasImport(chooser.getSelectedFile()))
1966 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1967 MessageManager.formatMessage(
1968 "label.couldnt_import_as_vamsas_session",
1972 .getString("label.vamsas_document_import_failed"),
1973 JvOptionPane.ERROR_MESSAGE);
1979 jalview.bin.Cache.log.error(
1980 "Implementation error - load session from a running session is not supported.");
1985 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1988 * @return true if import was a success and a session was started.
1990 public boolean vamsasImport(URL url)
1992 // TODO: create progress bar
1993 if (v_client != null)
1996 jalview.bin.Cache.log.error(
1997 "Implementation error - load session from a running session is not supported.");
2003 // copy the URL content to a temporary local file
2004 // TODO: be a bit cleverer here with nio (?!)
2005 File file = File.createTempFile("vdocfromurl", ".vdj");
2006 FileOutputStream fos = new FileOutputStream(file);
2007 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2008 byte[] buffer = new byte[2048];
2010 while ((ln = bis.read(buffer)) > -1)
2012 fos.write(buffer, 0, ln);
2016 v_client = new jalview.gui.VamsasApplication(this, file,
2017 url.toExternalForm());
2018 } catch (Exception ex)
2020 jalview.bin.Cache.log.error(
2021 "Failed to create new vamsas session from contents of URL "
2026 setupVamsasConnectedGui();
2027 v_client.initial_update(); // TODO: thread ?
2028 return v_client.inSession();
2032 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2035 * @return true if import was a success and a session was started.
2037 public boolean vamsasImport(File file)
2039 if (v_client != null)
2042 jalview.bin.Cache.log.error(
2043 "Implementation error - load session from a running session is not supported.");
2047 setProgressBar(MessageManager.formatMessage(
2048 "status.importing_vamsas_session_from", new Object[]
2049 { file.getName() }), file.hashCode());
2052 v_client = new jalview.gui.VamsasApplication(this, file, null);
2053 } catch (Exception ex)
2055 setProgressBar(MessageManager.formatMessage(
2056 "status.importing_vamsas_session_from", new Object[]
2057 { file.getName() }), file.hashCode());
2058 jalview.bin.Cache.log.error(
2059 "New vamsas session from existing session file failed:", ex);
2062 setupVamsasConnectedGui();
2063 v_client.initial_update(); // TODO: thread ?
2064 setProgressBar(MessageManager.formatMessage(
2065 "status.importing_vamsas_session_from", new Object[]
2066 { file.getName() }), file.hashCode());
2067 return v_client.inSession();
2070 public boolean joinVamsasSession(String mysesid)
2072 if (v_client != null)
2074 throw new Error(MessageManager
2075 .getString("error.try_join_vamsas_session_another"));
2077 if (mysesid == null)
2080 MessageManager.getString("error.invalid_vamsas_session_id"));
2082 v_client = new VamsasApplication(this, mysesid);
2083 setupVamsasConnectedGui();
2084 v_client.initial_update();
2085 return (v_client.inSession());
2089 public void vamsasStart_actionPerformed(ActionEvent e)
2091 if (v_client == null)
2094 // we just start a default session for moment.
2096 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2097 * getProperty("LAST_DIRECTORY"));
2099 * chooser.setFileView(new JalviewFileView());
2100 * chooser.setDialogTitle("Load Vamsas file");
2101 * chooser.setToolTipText("Import");
2103 * int value = chooser.showOpenDialog(this);
2105 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2106 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2108 v_client = new VamsasApplication(this);
2109 setupVamsasConnectedGui();
2110 v_client.initial_update(); // TODO: thread ?
2114 // store current data in session.
2115 v_client.push_update(); // TODO: thread
2119 protected void setupVamsasConnectedGui()
2121 vamsasStart.setText(MessageManager.getString("label.session_update"));
2122 vamsasSave.setVisible(true);
2123 vamsasStop.setVisible(true);
2124 vamsasImport.setVisible(false); // Document import to existing session is
2125 // not possible for vamsas-client-1.0.
2128 protected void setupVamsasDisconnectedGui()
2130 vamsasSave.setVisible(false);
2131 vamsasStop.setVisible(false);
2132 vamsasImport.setVisible(true);
2134 .setText(MessageManager.getString("label.new_vamsas_session"));
2138 public void vamsasStop_actionPerformed(ActionEvent e)
2140 if (v_client != null)
2142 v_client.end_session();
2144 setupVamsasDisconnectedGui();
2148 protected void buildVamsasStMenu()
2150 if (v_client == null)
2152 String[] sess = null;
2155 sess = VamsasApplication.getSessionList();
2156 } catch (Exception e)
2158 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2164 jalview.bin.Cache.log.debug(
2165 "Got current sessions list: " + sess.length + " entries.");
2166 VamsasStMenu.removeAll();
2167 for (int i = 0; i < sess.length; i++)
2169 JMenuItem sessit = new JMenuItem();
2170 sessit.setText(sess[i]);
2171 sessit.setToolTipText(MessageManager
2172 .formatMessage("label.connect_to_session", new Object[]
2174 final Desktop dsktp = this;
2175 final String mysesid = sess[i];
2176 sessit.addActionListener(new ActionListener()
2180 public void actionPerformed(ActionEvent e)
2182 if (dsktp.v_client == null)
2184 Thread rthr = new Thread(new Runnable()
2190 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2191 dsktp.setupVamsasConnectedGui();
2192 dsktp.v_client.initial_update();
2200 VamsasStMenu.add(sessit);
2202 // don't show an empty menu.
2203 VamsasStMenu.setVisible(sess.length > 0);
2208 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2209 VamsasStMenu.removeAll();
2210 VamsasStMenu.setVisible(false);
2215 // Not interested in the content. Just hide ourselves.
2216 VamsasStMenu.setVisible(false);
2221 public void vamsasSave_actionPerformed(ActionEvent e)
2223 if (v_client != null)
2225 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2226 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2229 chooser.setFileView(new JalviewFileView());
2230 chooser.setDialogTitle(MessageManager
2231 .getString("label.save_vamsas_document_archive"));
2233 int value = chooser.showSaveDialog(this);
2235 if (value == JalviewFileChooser.APPROVE_OPTION)
2237 java.io.File choice = chooser.getSelectedFile();
2238 JPanel progpanel = addProgressPanel(MessageManager
2239 .formatMessage("label.saving_vamsas_doc", new Object[]
2240 { choice.getName() }));
2241 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2242 String warnmsg = null;
2243 String warnttl = null;
2246 v_client.vclient.storeDocument(choice);
2249 warnttl = "Serious Problem saving Vamsas Document";
2250 warnmsg = ex.toString();
2251 jalview.bin.Cache.log
2252 .error("Error Whilst saving document to " + choice, ex);
2254 } catch (Exception ex)
2256 warnttl = "Problem saving Vamsas Document.";
2257 warnmsg = ex.toString();
2258 jalview.bin.Cache.log.warn(
2259 "Exception Whilst saving document to " + choice, ex);
2262 removeProgressPanel(progpanel);
2263 if (warnmsg != null)
2265 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2267 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2273 JPanel vamUpdate = null;
2276 * hide vamsas user gui bits when a vamsas document event is being handled.
2279 * true to hide gui, false to reveal gui
2281 public void setVamsasUpdate(boolean b)
2283 Cache.log.debug("Setting gui for Vamsas update "
2284 + (b ? "in progress" : "finished"));
2286 if (vamUpdate != null)
2288 this.removeProgressPanel(vamUpdate);
2292 vamUpdate = this.addProgressPanel(
2293 MessageManager.getString("label.updating_vamsas_session"));
2295 vamsasStart.setVisible(!b);
2296 vamsasStop.setVisible(!b);
2297 vamsasSave.setVisible(!b);
2300 public JInternalFrame[] getAllFrames()
2302 return desktop.getAllFrames();
2306 * Checks the given url to see if it gives a response indicating that the user
2307 * should be informed of a new questionnaire.
2311 public void checkForQuestionnaire(String url)
2313 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2314 // javax.swing.SwingUtilities.invokeLater(jvq);
2315 new Thread(jvq).start();
2318 public void checkURLLinks()
2320 // Thread off the URL link checker
2321 addDialogThread(new Runnable()
2326 if (Cache.getDefault("CHECKURLLINKS", true))
2328 // check what the actual links are - if it's just the default don't
2329 // bother with the warning
2330 List<String> links = Preferences.sequenceUrlLinks
2333 // only need to check links if there is one with a
2334 // SEQUENCE_ID which is not the default EMBL_EBI link
2335 ListIterator<String> li = links.listIterator();
2336 boolean check = false;
2337 List<JLabel> urls = new ArrayList<>();
2338 while (li.hasNext())
2340 String link = li.next();
2341 if (link.contains(SEQUENCE_ID)
2342 && !link.equals(UrlConstants.DEFAULT_STRING))
2345 int barPos = link.indexOf("|");
2346 String urlMsg = barPos == -1 ? link
2347 : link.substring(0, barPos) + ": "
2348 + link.substring(barPos + 1);
2349 urls.add(new JLabel(urlMsg));
2357 // ask user to check in case URL links use old style tokens
2358 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2359 JPanel msgPanel = new JPanel();
2360 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2361 msgPanel.add(Box.createVerticalGlue());
2362 JLabel msg = new JLabel(MessageManager
2363 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2364 JLabel msg2 = new JLabel(MessageManager
2365 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2367 for (JLabel url : urls)
2373 final JCheckBox jcb = new JCheckBox(
2374 MessageManager.getString("label.do_not_display_again"));
2375 jcb.addActionListener(new ActionListener()
2378 public void actionPerformed(ActionEvent e)
2380 // update Cache settings for "don't show this again"
2381 boolean showWarningAgain = !jcb.isSelected();
2382 Cache.setProperty("CHECKURLLINKS",
2383 Boolean.valueOf(showWarningAgain).toString());
2388 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2390 .getString("label.SEQUENCE_ID_no_longer_used"),
2391 JvOptionPane.WARNING_MESSAGE);
2398 * Proxy class for JDesktopPane which optionally displays the current memory
2399 * usage and highlights the desktop area with a red bar if free memory runs
2404 public class MyDesktopPane extends JDesktopPane implements Runnable
2407 private static final float ONE_MB = 1048576f;
2409 boolean showMemoryUsage = false;
2413 java.text.NumberFormat df;
2415 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2418 public MyDesktopPane(boolean showMemoryUsage)
2420 showMemoryUsage(showMemoryUsage);
2423 public void showMemoryUsage(boolean showMemory)
2425 this.showMemoryUsage = showMemory;
2428 Thread worker = new Thread(this);
2434 public boolean isShowMemoryUsage()
2436 return showMemoryUsage;
2442 df = java.text.NumberFormat.getNumberInstance();
2443 df.setMaximumFractionDigits(2);
2444 runtime = Runtime.getRuntime();
2446 while (showMemoryUsage)
2450 maxMemory = runtime.maxMemory() / ONE_MB;
2451 allocatedMemory = runtime.totalMemory() / ONE_MB;
2452 freeMemory = runtime.freeMemory() / ONE_MB;
2453 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2455 percentUsage = (totalFreeMemory / maxMemory) * 100;
2457 // if (percentUsage < 20)
2459 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2461 // instance.set.setBorder(border1);
2464 // sleep after showing usage
2466 } catch (Exception ex)
2468 ex.printStackTrace();
2474 public void paintComponent(Graphics g)
2476 if (showMemoryUsage && g != null && df != null)
2478 if (percentUsage < 20)
2480 g.setColor(Color.red);
2482 FontMetrics fm = g.getFontMetrics();
2485 g.drawString(MessageManager.formatMessage("label.memory_stats",
2487 { df.format(totalFreeMemory), df.format(maxMemory),
2488 df.format(percentUsage) }),
2489 10, getHeight() - fm.getHeight());
2497 * Accessor method to quickly get all the AlignmentFrames loaded.
2499 * @return an array of AlignFrame, or null if none found
2501 public static AlignFrame[] getAlignFrames()
2503 if (Jalview.isHeadlessMode())
2505 // Desktop.desktop is null in headless mode
2506 return new AlignFrame[] { Jalview.currentAlignFrame };
2509 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2515 List<AlignFrame> avp = new ArrayList<>();
2517 for (int i = frames.length - 1; i > -1; i--)
2519 if (frames[i] instanceof AlignFrame)
2521 avp.add((AlignFrame) frames[i]);
2523 else if (frames[i] instanceof SplitFrame)
2526 * Also check for a split frame containing an AlignFrame
2528 GSplitFrame sf = (GSplitFrame) frames[i];
2529 if (sf.getTopFrame() instanceof AlignFrame)
2531 avp.add((AlignFrame) sf.getTopFrame());
2533 if (sf.getBottomFrame() instanceof AlignFrame)
2535 avp.add((AlignFrame) sf.getBottomFrame());
2539 if (avp.size() == 0)
2543 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2548 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2552 public GStructureViewer[] getJmols()
2554 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2560 List<GStructureViewer> avp = new ArrayList<>();
2562 for (int i = frames.length - 1; i > -1; i--)
2564 if (frames[i] instanceof AppJmol)
2566 GStructureViewer af = (GStructureViewer) frames[i];
2570 if (avp.size() == 0)
2574 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2579 * Add Groovy Support to Jalview
2582 public void groovyShell_actionPerformed()
2586 openGroovyConsole();
2587 } catch (Exception ex)
2589 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2590 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2592 MessageManager.getString("label.couldnt_create_groovy_shell"),
2593 MessageManager.getString("label.groovy_support_failed"),
2594 JvOptionPane.ERROR_MESSAGE);
2599 * Open the Groovy console
2601 void openGroovyConsole()
2603 if (groovyConsole == null)
2605 groovyConsole = new groovy.ui.Console();
2606 groovyConsole.setVariable("Jalview", this);
2607 groovyConsole.run();
2610 * We allow only one console at a time, so that AlignFrame menu option
2611 * 'Calculate | Run Groovy script' is unambiguous.
2612 * Disable 'Groovy Console', and enable 'Run script', when the console is
2613 * opened, and the reverse when it is closed
2615 Window window = (Window) groovyConsole.getFrame();
2616 window.addWindowListener(new WindowAdapter()
2619 public void windowClosed(WindowEvent e)
2622 * rebind CMD-Q from Groovy Console to Jalview Quit
2625 enableExecuteGroovy(false);
2631 * show Groovy console window (after close and reopen)
2633 ((Window) groovyConsole.getFrame()).setVisible(true);
2636 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2637 * and disable opening a second console
2639 enableExecuteGroovy(true);
2643 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2644 * binding when opened
2646 protected void addQuitHandler()
2648 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2649 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2650 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2652 getRootPane().getActionMap().put("Quit", new AbstractAction()
2655 public void actionPerformed(ActionEvent e)
2663 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2666 * true if Groovy console is open
2668 public void enableExecuteGroovy(boolean enabled)
2671 * disable opening a second Groovy console
2672 * (or re-enable when the console is closed)
2674 groovyShell.setEnabled(!enabled);
2676 AlignFrame[] alignFrames = getAlignFrames();
2677 if (alignFrames != null)
2679 for (AlignFrame af : alignFrames)
2681 af.setGroovyEnabled(enabled);
2687 * Progress bars managed by the IProgressIndicator method.
2689 private Hashtable<Long, JPanel> progressBars;
2691 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2696 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2699 public void setProgressBar(String message, long id)
2701 if (progressBars == null)
2703 progressBars = new Hashtable<>();
2704 progressBarHandlers = new Hashtable<>();
2707 if (progressBars.get(new Long(id)) != null)
2709 JPanel panel = progressBars.remove(new Long(id));
2710 if (progressBarHandlers.contains(new Long(id)))
2712 progressBarHandlers.remove(new Long(id));
2714 removeProgressPanel(panel);
2718 progressBars.put(new Long(id), addProgressPanel(message));
2725 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2726 * jalview.gui.IProgressIndicatorHandler)
2729 public void registerHandler(final long id,
2730 final IProgressIndicatorHandler handler)
2732 if (progressBarHandlers == null
2733 || !progressBars.containsKey(new Long(id)))
2735 throw new Error(MessageManager.getString(
2736 "error.call_setprogressbar_before_registering_handler"));
2738 progressBarHandlers.put(new Long(id), handler);
2739 final JPanel progressPanel = progressBars.get(new Long(id));
2740 if (handler.canCancel())
2742 JButton cancel = new JButton(
2743 MessageManager.getString("action.cancel"));
2744 final IProgressIndicator us = this;
2745 cancel.addActionListener(new ActionListener()
2749 public void actionPerformed(ActionEvent e)
2751 handler.cancelActivity(id);
2752 us.setProgressBar(MessageManager
2753 .formatMessage("label.cancelled_params", new Object[]
2754 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2758 progressPanel.add(cancel, BorderLayout.EAST);
2764 * @return true if any progress bars are still active
2767 public boolean operationInProgress()
2769 if (progressBars != null && progressBars.size() > 0)
2777 * This will return the first AlignFrame holding the given viewport instance.
2778 * It will break if there are more than one AlignFrames viewing a particular
2782 * @return alignFrame for viewport
2784 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2786 if (desktop != null)
2788 AlignmentPanel[] aps = getAlignmentPanels(
2789 viewport.getSequenceSetId());
2790 for (int panel = 0; aps != null && panel < aps.length; panel++)
2792 if (aps[panel] != null && aps[panel].av == viewport)
2794 return aps[panel].alignFrame;
2801 public VamsasApplication getVamsasApplication()
2808 * flag set if jalview GUI is being operated programmatically
2810 private boolean inBatchMode = false;
2813 * check if jalview GUI is being operated programmatically
2815 * @return inBatchMode
2817 public boolean isInBatchMode()
2823 * set flag if jalview GUI is being operated programmatically
2825 * @param inBatchMode
2827 public void setInBatchMode(boolean inBatchMode)
2829 this.inBatchMode = inBatchMode;
2832 public void startServiceDiscovery()
2834 startServiceDiscovery(false);
2837 public void startServiceDiscovery(boolean blocking)
2839 boolean alive = true;
2840 Thread t0 = null, t1 = null, t2 = null;
2841 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2844 // todo: changesupport handlers need to be transferred
2845 if (discoverer == null)
2847 discoverer = new jalview.ws.jws1.Discoverer();
2848 // register PCS handler for desktop.
2849 discoverer.addPropertyChangeListener(changeSupport);
2851 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2852 // until we phase out completely
2853 (t0 = new Thread(discoverer)).start();
2856 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2858 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2859 .startDiscoverer(changeSupport);
2863 // TODO: do rest service discovery
2872 } catch (Exception e)
2875 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2876 || (t3 != null && t3.isAlive())
2877 || (t0 != null && t0.isAlive());
2883 * called to check if the service discovery process completed successfully.
2887 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2889 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2891 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2892 .getErrorMessages();
2895 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2897 if (serviceChangedDialog == null)
2899 // only run if we aren't already displaying one of these.
2900 addDialogThread(serviceChangedDialog = new Runnable()
2907 * JalviewDialog jd =new JalviewDialog() {
2909 * @Override protected void cancelPressed() { // TODO
2910 * Auto-generated method stub
2912 * }@Override protected void okPressed() { // TODO
2913 * Auto-generated method stub
2915 * }@Override protected void raiseClosed() { // TODO
2916 * Auto-generated method stub
2918 * } }; jd.initDialogFrame(new
2919 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2920 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2921 * + " or mis-configured HTTP proxy settings.<br/>" +
2922 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2924 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2925 * ), true, true, "Web Service Configuration Problem", 450,
2928 * jd.waitForInput();
2930 JvOptionPane.showConfirmDialog(Desktop.desktop,
2931 new JLabel("<html><table width=\"450\"><tr><td>"
2932 + ermsg + "</td></tr></table>"
2933 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2934 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2935 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2936 + " Tools->Preferences dialog box to change them.</p></html>"),
2937 "Web Service Configuration Problem",
2938 JvOptionPane.DEFAULT_OPTION,
2939 JvOptionPane.ERROR_MESSAGE);
2940 serviceChangedDialog = null;
2949 "Errors reported by JABA discovery service. Check web services preferences.\n"
2956 private Runnable serviceChangedDialog = null;
2959 * start a thread to open a URL in the configured browser. Pops up a warning
2960 * dialog to the user if there is an exception when calling out to the browser
2965 public static void showUrl(final String url)
2967 showUrl(url, Desktop.instance);
2971 * Like showUrl but allows progress handler to be specified
2975 * (null) or object implementing IProgressIndicator
2977 public static void showUrl(final String url,
2978 final IProgressIndicator progress)
2980 new Thread(new Runnable()
2987 if (progress != null)
2989 progress.setProgressBar(MessageManager
2990 .formatMessage("status.opening_params", new Object[]
2991 { url }), this.hashCode());
2993 jalview.util.BrowserLauncher.openURL(url);
2994 } catch (Exception ex)
2996 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2998 .getString("label.web_browser_not_found_unix"),
2999 MessageManager.getString("label.web_browser_not_found"),
3000 JvOptionPane.WARNING_MESSAGE);
3002 ex.printStackTrace();
3004 if (progress != null)
3006 progress.setProgressBar(null, this.hashCode());
3012 public static WsParamSetManager wsparamManager = null;
3014 public static ParamManager getUserParameterStore()
3016 if (wsparamManager == null)
3018 wsparamManager = new WsParamSetManager();
3020 return wsparamManager;
3024 * static hyperlink handler proxy method for use by Jalview's internal windows
3028 public static void hyperlinkUpdate(HyperlinkEvent e)
3030 if (e.getEventType() == EventType.ACTIVATED)
3035 url = e.getURL().toString();
3036 Desktop.showUrl(url);
3037 } catch (Exception x)
3041 if (Cache.log != null)
3043 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3048 "Couldn't handle string " + url + " as a URL.");
3051 // ignore any exceptions due to dud links.
3058 * single thread that handles display of dialogs to user.
3060 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3063 * flag indicating if dialogExecutor should try to acquire a permit
3065 private volatile boolean dialogPause = true;
3070 private java.util.concurrent.Semaphore block = new Semaphore(0);
3072 private static groovy.ui.Console groovyConsole;
3075 * add another dialog thread to the queue
3079 public void addDialogThread(final Runnable prompter)
3081 dialogExecutor.submit(new Runnable()
3091 } catch (InterruptedException x)
3096 if (instance == null)
3102 SwingUtilities.invokeAndWait(prompter);
3103 } catch (Exception q)
3105 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3111 public void startDialogQueue()
3113 // set the flag so we don't pause waiting for another permit and semaphore
3114 // the current task to begin
3115 dialogPause = false;
3120 protected void snapShotWindow_actionPerformed(ActionEvent e)
3124 ImageMaker im = new jalview.util.ImageMaker(
3125 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3126 getHeight(), of = new File("Jalview_snapshot"
3127 + System.currentTimeMillis() + ".eps"),
3128 "View of desktop", null, 0, false);
3131 paintAll(im.getGraphics());
3133 } catch (Exception q)
3135 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3139 Cache.log.info("Successfully written snapshot to file "
3140 + of.getAbsolutePath());
3144 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3145 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3146 * and location last time the view was expanded (if any). However it does not
3147 * remember the split pane divider location - this is set to match the
3148 * 'exploding' frame.
3152 public void explodeViews(SplitFrame sf)
3154 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3155 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3156 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3158 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3160 int viewCount = topPanels.size();
3167 * Processing in reverse order works, forwards order leaves the first panels
3168 * not visible. I don't know why!
3170 for (int i = viewCount - 1; i >= 0; i--)
3173 * Make new top and bottom frames. These take over the respective
3174 * AlignmentPanel objects, including their AlignmentViewports, so the
3175 * cdna/protein relationships between the viewports is carried over to the
3178 * explodedGeometry holds the (x, y) position of the previously exploded
3179 * SplitFrame, and the (width, height) of the AlignFrame component
3181 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3182 AlignFrame newTopFrame = new AlignFrame(topPanel);
3183 newTopFrame.setSize(oldTopFrame.getSize());
3184 newTopFrame.setVisible(true);
3185 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3186 .getExplodedGeometry();
3187 if (geometry != null)
3189 newTopFrame.setSize(geometry.getSize());
3192 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3193 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3194 newBottomFrame.setSize(oldBottomFrame.getSize());
3195 newBottomFrame.setVisible(true);
3196 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3197 .getExplodedGeometry();
3198 if (geometry != null)
3200 newBottomFrame.setSize(geometry.getSize());
3203 topPanel.av.setGatherViewsHere(false);
3204 bottomPanel.av.setGatherViewsHere(false);
3205 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3207 if (geometry != null)
3209 splitFrame.setLocation(geometry.getLocation());
3211 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3215 * Clear references to the panels (now relocated in the new SplitFrames)
3216 * before closing the old SplitFrame.
3219 bottomPanels.clear();
3224 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3225 * back into the given SplitFrame as additional views. Note that the gathered
3226 * frames may themselves have multiple views.
3230 public void gatherViews(GSplitFrame source)
3233 * special handling of explodedGeometry for a view within a SplitFrame: - it
3234 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3235 * height) of the AlignFrame component
3237 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3238 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3239 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3240 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3241 myBottomFrame.viewport
3242 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3243 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3244 myTopFrame.viewport.setGatherViewsHere(true);
3245 myBottomFrame.viewport.setGatherViewsHere(true);
3246 String topViewId = myTopFrame.viewport.getSequenceSetId();
3247 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3249 JInternalFrame[] frames = desktop.getAllFrames();
3250 for (JInternalFrame frame : frames)
3252 if (frame instanceof SplitFrame && frame != source)
3254 SplitFrame sf = (SplitFrame) frame;
3255 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3256 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3257 boolean gatherThis = false;
3258 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3260 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3261 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3262 if (topViewId.equals(topPanel.av.getSequenceSetId())
3263 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3266 topPanel.av.setGatherViewsHere(false);
3267 bottomPanel.av.setGatherViewsHere(false);
3268 topPanel.av.setExplodedGeometry(
3269 new Rectangle(sf.getLocation(), topFrame.getSize()));
3270 bottomPanel.av.setExplodedGeometry(
3271 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3272 myTopFrame.addAlignmentPanel(topPanel, false);
3273 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3279 topFrame.getAlignPanels().clear();
3280 bottomFrame.getAlignPanels().clear();
3287 * The dust settles...give focus to the tab we did this from.
3289 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3292 public static groovy.ui.Console getGroovyConsole()
3294 return groovyConsole;
3297 public static void transferFromDropTarget(List<String> files,
3298 List<DataSourceType> protocols, DropTargetDropEvent evt,
3299 Transferable t) throws Exception
3302 DataFlavor uriListFlavor = new DataFlavor(
3303 "text/uri-list;class=java.lang.String");
3304 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3306 // Works on Windows and MacOSX
3307 Cache.log.debug("Drop handled as javaFileListFlavor");
3308 for (Object file : (List) t
3309 .getTransferData(DataFlavor.javaFileListFlavor))
3311 files.add(((File) file).toString());
3312 protocols.add(DataSourceType.FILE);
3317 // Unix like behaviour
3318 boolean added = false;
3320 if (t.isDataFlavorSupported(uriListFlavor))
3322 Cache.log.debug("Drop handled as uriListFlavor");
3323 // This is used by Unix drag system
3324 data = (String) t.getTransferData(uriListFlavor);
3328 // fallback to text: workaround - on OSX where there's a JVM bug
3329 Cache.log.debug("standard URIListFlavor failed. Trying text");
3330 // try text fallback
3331 data = (String) t.getTransferData(
3332 new DataFlavor("text/plain;class=java.lang.String"));
3333 if (Cache.log.isDebugEnabled())
3335 Cache.log.debug("fallback returned " + data);
3338 while (protocols.size() < files.size())
3340 Cache.log.debug("Adding missing FILE protocol for "
3341 + files.get(protocols.size()));
3342 protocols.add(DataSourceType.FILE);
3344 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3345 data, "\r\n"); st.hasMoreTokens();)
3348 String s = st.nextToken();
3349 if (s.startsWith("#"))
3351 // the line is a comment (as per the RFC 2483)
3354 java.net.URI uri = new java.net.URI(s);
3355 if (uri.getScheme().toLowerCase().startsWith("http"))
3357 protocols.add(DataSourceType.URL);
3358 files.add(uri.toString());
3362 // otherwise preserve old behaviour: catch all for file objects
3363 java.io.File file = new java.io.File(uri);
3364 protocols.add(DataSourceType.FILE);
3365 files.add(file.toString());
3368 if (Cache.log.isDebugEnabled())
3370 if (data == null || !added)
3373 "Couldn't resolve drop data. Here are the supported flavors:");
3374 for (DataFlavor fl : t.getTransferDataFlavors())
3377 "Supported transfer dataflavor: " + fl.toString());
3378 Object df = t.getTransferData(fl);
3381 Cache.log.debug("Retrieves: " + df);
3385 Cache.log.debug("Retrieved nothing");
3394 * Sets the Preferences property for experimental features to True or False
3395 * depending on the state of the controlling menu item
3398 protected void showExperimental_actionPerformed(boolean selected)
3400 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));