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);
881 public void internalFrameClosed(InternalFrameEvent evt)
883 PaintRefresher.RemoveComponent(frame);
886 * defensive check to prevent frames being
887 * added half off the window
889 if (openFrameCount > 0)
895 * ensure no reference to alignFrame retained by menu item listener
897 if (menuItem.getActionListeners().length > 0)
899 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
901 windowMenu.remove(menuItem);
905 menuItem.addActionListener(new ActionListener()
908 public void actionPerformed(ActionEvent e)
912 frame.setSelected(true);
913 frame.setIcon(false);
914 } catch (java.beans.PropertyVetoException ex)
923 windowMenu.add(menuItem);
928 frame.setSelected(true);
929 frame.requestFocus();
930 } catch (java.beans.PropertyVetoException ve)
932 } catch (java.lang.ClassCastException cex)
935 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
941 public void lostOwnership(Clipboard clipboard, Transferable contents)
945 Desktop.jalviewClipboard = null;
948 internalCopy = false;
952 public void dragEnter(DropTargetDragEvent evt)
957 public void dragExit(DropTargetEvent evt)
962 public void dragOver(DropTargetDragEvent evt)
967 public void dropActionChanged(DropTargetDragEvent evt)
978 public void drop(DropTargetDropEvent evt)
980 boolean success = true;
981 // JAL-1552 - acceptDrop required before getTransferable call for
982 // Java's Transferable for native dnd
983 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
984 Transferable t = evt.getTransferable();
985 List<String> files = new ArrayList<>();
986 List<DataSourceType> protocols = new ArrayList<>();
990 Desktop.transferFromDropTarget(files, protocols, evt, t);
991 } catch (Exception e)
1001 for (int i = 0; i < files.size(); i++)
1003 String file = files.get(i).toString();
1004 DataSourceType protocol = (protocols == null)
1005 ? DataSourceType.FILE
1007 FileFormatI format = null;
1009 if (file.endsWith(".jar"))
1011 format = FileFormat.Jalview;
1016 format = new IdentifyFile().identify(file, protocol);
1019 new FileLoader().LoadFile(file, protocol, format);
1022 } catch (Exception ex)
1027 evt.dropComplete(success); // need this to ensure input focus is properly
1028 // transfered to any new windows created
1038 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1040 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1041 JalviewFileChooser chooser = JalviewFileChooser
1042 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1044 chooser.setFileView(new JalviewFileView());
1045 chooser.setDialogTitle(
1046 MessageManager.getString("label.open_local_file"));
1047 chooser.setToolTipText(MessageManager.getString("action.open"));
1049 int value = chooser.showOpenDialog(this);
1051 if (value == JalviewFileChooser.APPROVE_OPTION)
1053 String choice = chooser.getSelectedFile().getPath();
1054 Cache.setProperty("LAST_DIRECTORY",
1055 chooser.getSelectedFile().getParent());
1057 FileFormatI format = chooser.getSelectedFormat();
1060 * Call IdentifyFile to verify the file contains what its extension implies.
1061 * Skip this step for dynamically added file formats, because
1062 * IdentifyFile does not know how to recognise them.
1064 if (FileFormats.getInstance().isIdentifiable(format))
1068 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1069 } catch (FileFormatException e)
1071 // format = null; //??
1075 if (viewport != null)
1077 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1082 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1094 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1096 // This construct allows us to have a wider textfield
1098 JLabel label = new JLabel(
1099 MessageManager.getString("label.input_file_url"));
1100 final JComboBox history = new JComboBox();
1102 JPanel panel = new JPanel(new GridLayout(2, 1));
1105 history.setPreferredSize(new Dimension(400, 20));
1106 history.setEditable(true);
1107 history.addItem("http://www.");
1109 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1113 if (historyItems != null)
1115 st = new StringTokenizer(historyItems, "\t");
1117 while (st.hasMoreTokens())
1119 history.addItem(st.nextElement());
1123 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1124 MessageManager.getString("label.input_alignment_from_url"),
1125 JvOptionPane.OK_CANCEL_OPTION);
1127 if (reply != JvOptionPane.OK_OPTION)
1132 String url = history.getSelectedItem().toString();
1134 if (url.toLowerCase().endsWith(".jar"))
1136 if (viewport != null)
1138 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1139 FileFormat.Jalview);
1143 new FileLoader().LoadFile(url, DataSourceType.URL,
1144 FileFormat.Jalview);
1149 FileFormatI format = null;
1152 format = new IdentifyFile().identify(url, DataSourceType.URL);
1153 } catch (FileFormatException e)
1155 // TODO revise error handling, distinguish between
1156 // URL not found and response not valid
1161 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1162 MessageManager.formatMessage("label.couldnt_locate",
1165 MessageManager.getString("label.url_not_found"),
1166 JvOptionPane.WARNING_MESSAGE);
1171 if (viewport != null)
1173 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1178 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1184 * Opens the CutAndPaste window for the user to paste an alignment in to
1187 * - if not null, the pasted alignment is added to the current
1188 * alignment; if null, to a new alignment window
1191 public void inputTextboxMenuItem_actionPerformed(
1192 AlignmentViewPanel viewPanel)
1194 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1195 cap.setForInput(viewPanel);
1196 Desktop.addInternalFrame(cap,
1197 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1207 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1208 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1210 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1211 screen.height + "");
1212 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1213 getWidth(), getHeight()));
1215 if (jconsole != null)
1217 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1218 jconsole.stopConsole();
1222 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1225 if (dialogExecutor != null)
1227 dialogExecutor.shutdownNow();
1229 closeAll_actionPerformed(null);
1231 if (groovyConsole != null)
1233 // suppress a possible repeat prompt to save script
1234 groovyConsole.setDirty(false);
1235 groovyConsole.exit();
1240 private void storeLastKnownDimensions(String string, Rectangle jc)
1242 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1243 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1244 + " height:" + jc.height);
1246 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1247 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1248 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1249 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1259 public void aboutMenuItem_actionPerformed(ActionEvent e)
1261 // StringBuffer message = getAboutMessage(false);
1262 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1264 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1265 new Thread(new Runnable()
1270 new SplashScreen(true);
1275 public StringBuffer getAboutMessage(boolean shortv)
1277 StringBuffer message = new StringBuffer();
1278 message.append("<html>");
1281 message.append("<h1><strong>Version: "
1282 + jalview.bin.Cache.getProperty("VERSION")
1283 + "</strong></h1>");
1284 message.append("<strong>Last Updated: <em>"
1285 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1286 + "</em></strong>");
1292 message.append("<strong>Version "
1293 + jalview.bin.Cache.getProperty("VERSION")
1294 + "; last updated: "
1295 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1298 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1299 .equals("Checking"))
1301 message.append("<br>...Checking latest version...</br>");
1303 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1304 .equals(jalview.bin.Cache.getProperty("VERSION")))
1306 boolean red = false;
1307 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1308 .indexOf("automated build") == -1)
1311 // Displayed when code version and jnlp version do not match and code
1312 // version is not a development build
1313 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1316 message.append("<br>!! Version "
1317 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1319 + " is available for download from "
1320 + jalview.bin.Cache.getDefault("www.jalview.org",
1321 "http://www.jalview.org")
1325 message.append("</div>");
1328 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1330 "The Jalview Authors (See AUTHORS file for current list)")
1331 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1332 + "<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"
1333 + "<br><br>If you use Jalview, please cite:"
1334 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1335 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1336 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1348 public void documentationMenuItem_actionPerformed(ActionEvent e)
1352 Help.showHelpWindow();
1353 } catch (Exception ex)
1359 public void closeAll_actionPerformed(ActionEvent e)
1361 // TODO show a progress bar while closing?
1362 JInternalFrame[] frames = desktop.getAllFrames();
1363 for (int i = 0; i < frames.length; i++)
1367 frames[i].setClosed(true);
1368 } catch (java.beans.PropertyVetoException ex)
1372 Jalview.setCurrentAlignFrame(null);
1373 System.out.println("ALL CLOSED");
1374 if (v_client != null)
1376 // TODO clear binding to vamsas document objects on close_all
1380 * reset state of singleton objects as appropriate (clear down session state
1381 * when all windows are closed)
1383 StructureSelectionManager ssm = StructureSelectionManager
1384 .getStructureSelectionManager(this);
1392 public void raiseRelated_actionPerformed(ActionEvent e)
1394 reorderAssociatedWindows(false, false);
1398 public void minimizeAssociated_actionPerformed(ActionEvent e)
1400 reorderAssociatedWindows(true, false);
1403 void closeAssociatedWindows()
1405 reorderAssociatedWindows(false, true);
1411 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1415 protected void garbageCollect_actionPerformed(ActionEvent e)
1417 // We simply collect the garbage
1418 jalview.bin.Cache.log.debug("Collecting garbage...");
1420 jalview.bin.Cache.log.debug("Finished garbage collection.");
1427 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1431 protected void showMemusage_actionPerformed(ActionEvent e)
1433 desktop.showMemoryUsage(showMemusage.isSelected());
1440 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1444 protected void showConsole_actionPerformed(ActionEvent e)
1446 showConsole(showConsole.isSelected());
1449 Console jconsole = null;
1452 * control whether the java console is visible or not
1456 void showConsole(boolean selected)
1458 showConsole.setSelected(selected);
1459 // TODO: decide if we should update properties file
1460 Cache.setProperty("SHOW_JAVA_CONSOLE",
1461 Boolean.valueOf(selected).toString());
1462 jconsole.setVisible(selected);
1465 void reorderAssociatedWindows(boolean minimize, boolean close)
1467 JInternalFrame[] frames = desktop.getAllFrames();
1468 if (frames == null || frames.length < 1)
1473 AlignmentViewport source = null, target = null;
1474 if (frames[0] instanceof AlignFrame)
1476 source = ((AlignFrame) frames[0]).getCurrentView();
1478 else if (frames[0] instanceof TreePanel)
1480 source = ((TreePanel) frames[0]).getViewPort();
1482 else if (frames[0] instanceof PCAPanel)
1484 source = ((PCAPanel) frames[0]).av;
1486 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1488 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1493 for (int i = 0; i < frames.length; i++)
1496 if (frames[i] == null)
1500 if (frames[i] instanceof AlignFrame)
1502 target = ((AlignFrame) frames[i]).getCurrentView();
1504 else if (frames[i] instanceof TreePanel)
1506 target = ((TreePanel) frames[i]).getViewPort();
1508 else if (frames[i] instanceof PCAPanel)
1510 target = ((PCAPanel) frames[i]).av;
1512 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1514 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1517 if (source == target)
1523 frames[i].setClosed(true);
1527 frames[i].setIcon(minimize);
1530 frames[i].toFront();
1534 } catch (java.beans.PropertyVetoException ex)
1549 protected void preferences_actionPerformed(ActionEvent e)
1561 public void saveState_actionPerformed(ActionEvent e)
1563 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1566 chooser.setFileView(new JalviewFileView());
1567 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1569 int value = chooser.showSaveDialog(this);
1571 if (value == JalviewFileChooser.APPROVE_OPTION)
1573 final Desktop me = this;
1574 final java.io.File choice = chooser.getSelectedFile();
1575 setProjectFile(choice);
1577 new Thread(new Runnable()
1582 // TODO: refactor to Jalview desktop session controller action.
1583 setProgressBar(MessageManager.formatMessage(
1584 "label.saving_jalview_project", new Object[]
1585 { choice.getName() }), choice.hashCode());
1586 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1587 choice.getParent());
1588 // TODO catch and handle errors for savestate
1589 // TODO prevent user from messing with the Desktop whilst we're saving
1592 new Jalview2XML().saveState(choice);
1593 } catch (OutOfMemoryError oom)
1596 "Whilst saving current state to " + choice.getName(),
1598 } catch (Exception ex)
1601 "Problems whilst trying to save to " + choice.getName(),
1603 JvOptionPane.showMessageDialog(me,
1604 MessageManager.formatMessage(
1605 "label.error_whilst_saving_current_state_to",
1607 { choice.getName() }),
1608 MessageManager.getString("label.couldnt_save_project"),
1609 JvOptionPane.WARNING_MESSAGE);
1611 setProgressBar(null, choice.hashCode());
1617 private void setProjectFile(File choice)
1619 this.projectFile = choice;
1622 public File getProjectFile()
1624 return this.projectFile;
1634 public void loadState_actionPerformed(ActionEvent e)
1636 JalviewFileChooser chooser = new JalviewFileChooser(
1637 Cache.getProperty("LAST_DIRECTORY"), new String[]
1640 { "Jalview Project", "Jalview Project (old)" },
1642 chooser.setFileView(new JalviewFileView());
1643 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1645 int value = chooser.showOpenDialog(this);
1647 if (value == JalviewFileChooser.APPROVE_OPTION)
1649 final File selectedFile = chooser.getSelectedFile();
1650 setProjectFile(selectedFile);
1651 final String choice = selectedFile.getAbsolutePath();
1652 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1653 new Thread(new Runnable()
1658 setProgressBar(MessageManager.formatMessage(
1659 "label.loading_jalview_project", new Object[]
1660 { choice }), choice.hashCode());
1663 new Jalview2XML().loadJalviewAlign(choice);
1664 } catch (OutOfMemoryError oom)
1666 new OOMWarning("Whilst loading project from " + choice, oom);
1667 } catch (Exception ex)
1670 "Problems whilst loading project from " + choice, ex);
1671 JvOptionPane.showMessageDialog(Desktop.desktop,
1672 MessageManager.formatMessage(
1673 "label.error_whilst_loading_project_from",
1676 MessageManager.getString("label.couldnt_load_project"),
1677 JvOptionPane.WARNING_MESSAGE);
1679 setProgressBar(null, choice.hashCode());
1686 public void inputSequence_actionPerformed(ActionEvent e)
1688 new SequenceFetcher(this);
1691 JPanel progressPanel;
1693 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1695 public void startLoading(final String fileName)
1697 if (fileLoadingCount == 0)
1699 fileLoadingPanels.add(addProgressPanel(MessageManager
1700 .formatMessage("label.loading_file", new Object[]
1706 private JPanel addProgressPanel(String string)
1708 if (progressPanel == null)
1710 progressPanel = new JPanel(new GridLayout(1, 1));
1711 totalProgressCount = 0;
1712 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1714 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1715 JProgressBar progressBar = new JProgressBar();
1716 progressBar.setIndeterminate(true);
1718 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1720 thisprogress.add(progressBar, BorderLayout.CENTER);
1721 progressPanel.add(thisprogress);
1722 ((GridLayout) progressPanel.getLayout()).setRows(
1723 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1724 ++totalProgressCount;
1725 instance.validate();
1726 return thisprogress;
1729 int totalProgressCount = 0;
1731 private void removeProgressPanel(JPanel progbar)
1733 if (progressPanel != null)
1735 synchronized (progressPanel)
1737 progressPanel.remove(progbar);
1738 GridLayout gl = (GridLayout) progressPanel.getLayout();
1739 gl.setRows(gl.getRows() - 1);
1740 if (--totalProgressCount < 1)
1742 this.getContentPane().remove(progressPanel);
1743 progressPanel = null;
1750 public void stopLoading()
1753 if (fileLoadingCount < 1)
1755 while (fileLoadingPanels.size() > 0)
1757 removeProgressPanel(fileLoadingPanels.remove(0));
1759 fileLoadingPanels.clear();
1760 fileLoadingCount = 0;
1765 public static int getViewCount(String alignmentId)
1767 AlignmentViewport[] aps = getViewports(alignmentId);
1768 return (aps == null) ? 0 : aps.length;
1773 * @param alignmentId
1774 * - if null, all sets are returned
1775 * @return all AlignmentPanels concerning the alignmentId sequence set
1777 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1779 if (Desktop.desktop == null)
1781 // no frames created and in headless mode
1782 // TODO: verify that frames are recoverable when in headless mode
1785 List<AlignmentPanel> aps = new ArrayList<>();
1786 AlignFrame[] frames = getAlignFrames();
1791 for (AlignFrame af : frames)
1793 for (AlignmentPanel ap : af.alignPanels)
1795 if (alignmentId == null
1796 || alignmentId.equals(ap.av.getSequenceSetId()))
1802 if (aps.size() == 0)
1806 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1811 * get all the viewports on an alignment.
1813 * @param sequenceSetId
1814 * unique alignment id (may be null - all viewports returned in that
1816 * @return all viewports on the alignment bound to sequenceSetId
1818 public static AlignmentViewport[] getViewports(String sequenceSetId)
1820 List<AlignmentViewport> viewp = new ArrayList<>();
1821 if (desktop != null)
1823 AlignFrame[] frames = Desktop.getAlignFrames();
1825 for (AlignFrame afr : frames)
1827 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1828 .equals(sequenceSetId))
1830 if (afr.alignPanels != null)
1832 for (AlignmentPanel ap : afr.alignPanels)
1834 if (sequenceSetId == null
1835 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1843 viewp.add(afr.getViewport());
1847 if (viewp.size() > 0)
1849 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1856 * Explode the views in the given frame into separate AlignFrame
1860 public static void explodeViews(AlignFrame af)
1862 int size = af.alignPanels.size();
1868 for (int i = 0; i < size; i++)
1870 AlignmentPanel ap = af.alignPanels.get(i);
1871 AlignFrame newaf = new AlignFrame(ap);
1874 * Restore the view's last exploded frame geometry if known. Multiple
1875 * views from one exploded frame share and restore the same (frame)
1876 * position and size.
1878 Rectangle geometry = ap.av.getExplodedGeometry();
1879 if (geometry != null)
1881 newaf.setBounds(geometry);
1884 ap.av.setGatherViewsHere(false);
1886 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1887 AlignFrame.DEFAULT_HEIGHT);
1890 af.alignPanels.clear();
1891 af.closeMenuItem_actionPerformed(true);
1896 * Gather expanded views (separate AlignFrame's) with the same sequence set
1897 * identifier back in to this frame as additional views, and close the
1898 * expanded views. Note the expanded frames may themselves have multiple
1899 * views. We take the lot.
1903 public void gatherViews(AlignFrame source)
1905 source.viewport.setGatherViewsHere(true);
1906 source.viewport.setExplodedGeometry(source.getBounds());
1907 JInternalFrame[] frames = desktop.getAllFrames();
1908 String viewId = source.viewport.getSequenceSetId();
1910 for (int t = 0; t < frames.length; t++)
1912 if (frames[t] instanceof AlignFrame && frames[t] != source)
1914 AlignFrame af = (AlignFrame) frames[t];
1915 boolean gatherThis = false;
1916 for (int a = 0; a < af.alignPanels.size(); a++)
1918 AlignmentPanel ap = af.alignPanels.get(a);
1919 if (viewId.equals(ap.av.getSequenceSetId()))
1922 ap.av.setGatherViewsHere(false);
1923 ap.av.setExplodedGeometry(af.getBounds());
1924 source.addAlignmentPanel(ap, false);
1930 af.alignPanels.clear();
1931 af.closeMenuItem_actionPerformed(true);
1938 jalview.gui.VamsasApplication v_client = null;
1941 public void vamsasImport_actionPerformed(ActionEvent e)
1943 if (v_client == null)
1945 // Load and try to start a session.
1946 JalviewFileChooser chooser = new JalviewFileChooser(
1947 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1949 chooser.setFileView(new JalviewFileView());
1950 chooser.setDialogTitle(
1951 MessageManager.getString("label.open_saved_vamsas_session"));
1952 chooser.setToolTipText(MessageManager.getString(
1953 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1955 int value = chooser.showOpenDialog(this);
1957 if (value == JalviewFileChooser.APPROVE_OPTION)
1959 String fle = chooser.getSelectedFile().toString();
1960 if (!vamsasImport(chooser.getSelectedFile()))
1962 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1963 MessageManager.formatMessage(
1964 "label.couldnt_import_as_vamsas_session",
1968 .getString("label.vamsas_document_import_failed"),
1969 JvOptionPane.ERROR_MESSAGE);
1975 jalview.bin.Cache.log.error(
1976 "Implementation error - load session from a running session is not supported.");
1981 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1984 * @return true if import was a success and a session was started.
1986 public boolean vamsasImport(URL url)
1988 // TODO: create progress bar
1989 if (v_client != null)
1992 jalview.bin.Cache.log.error(
1993 "Implementation error - load session from a running session is not supported.");
1999 // copy the URL content to a temporary local file
2000 // TODO: be a bit cleverer here with nio (?!)
2001 File file = File.createTempFile("vdocfromurl", ".vdj");
2002 FileOutputStream fos = new FileOutputStream(file);
2003 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2004 byte[] buffer = new byte[2048];
2006 while ((ln = bis.read(buffer)) > -1)
2008 fos.write(buffer, 0, ln);
2012 v_client = new jalview.gui.VamsasApplication(this, file,
2013 url.toExternalForm());
2014 } catch (Exception ex)
2016 jalview.bin.Cache.log.error(
2017 "Failed to create new vamsas session from contents of URL "
2022 setupVamsasConnectedGui();
2023 v_client.initial_update(); // TODO: thread ?
2024 return v_client.inSession();
2028 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2031 * @return true if import was a success and a session was started.
2033 public boolean vamsasImport(File file)
2035 if (v_client != null)
2038 jalview.bin.Cache.log.error(
2039 "Implementation error - load session from a running session is not supported.");
2043 setProgressBar(MessageManager.formatMessage(
2044 "status.importing_vamsas_session_from", new Object[]
2045 { file.getName() }), file.hashCode());
2048 v_client = new jalview.gui.VamsasApplication(this, file, null);
2049 } catch (Exception ex)
2051 setProgressBar(MessageManager.formatMessage(
2052 "status.importing_vamsas_session_from", new Object[]
2053 { file.getName() }), file.hashCode());
2054 jalview.bin.Cache.log.error(
2055 "New vamsas session from existing session file failed:", ex);
2058 setupVamsasConnectedGui();
2059 v_client.initial_update(); // TODO: thread ?
2060 setProgressBar(MessageManager.formatMessage(
2061 "status.importing_vamsas_session_from", new Object[]
2062 { file.getName() }), file.hashCode());
2063 return v_client.inSession();
2066 public boolean joinVamsasSession(String mysesid)
2068 if (v_client != null)
2070 throw new Error(MessageManager
2071 .getString("error.try_join_vamsas_session_another"));
2073 if (mysesid == null)
2076 MessageManager.getString("error.invalid_vamsas_session_id"));
2078 v_client = new VamsasApplication(this, mysesid);
2079 setupVamsasConnectedGui();
2080 v_client.initial_update();
2081 return (v_client.inSession());
2085 public void vamsasStart_actionPerformed(ActionEvent e)
2087 if (v_client == null)
2090 // we just start a default session for moment.
2092 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2093 * getProperty("LAST_DIRECTORY"));
2095 * chooser.setFileView(new JalviewFileView());
2096 * chooser.setDialogTitle("Load Vamsas file");
2097 * chooser.setToolTipText("Import");
2099 * int value = chooser.showOpenDialog(this);
2101 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2102 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2104 v_client = new VamsasApplication(this);
2105 setupVamsasConnectedGui();
2106 v_client.initial_update(); // TODO: thread ?
2110 // store current data in session.
2111 v_client.push_update(); // TODO: thread
2115 protected void setupVamsasConnectedGui()
2117 vamsasStart.setText(MessageManager.getString("label.session_update"));
2118 vamsasSave.setVisible(true);
2119 vamsasStop.setVisible(true);
2120 vamsasImport.setVisible(false); // Document import to existing session is
2121 // not possible for vamsas-client-1.0.
2124 protected void setupVamsasDisconnectedGui()
2126 vamsasSave.setVisible(false);
2127 vamsasStop.setVisible(false);
2128 vamsasImport.setVisible(true);
2130 .setText(MessageManager.getString("label.new_vamsas_session"));
2134 public void vamsasStop_actionPerformed(ActionEvent e)
2136 if (v_client != null)
2138 v_client.end_session();
2140 setupVamsasDisconnectedGui();
2144 protected void buildVamsasStMenu()
2146 if (v_client == null)
2148 String[] sess = null;
2151 sess = VamsasApplication.getSessionList();
2152 } catch (Exception e)
2154 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2160 jalview.bin.Cache.log.debug(
2161 "Got current sessions list: " + sess.length + " entries.");
2162 VamsasStMenu.removeAll();
2163 for (int i = 0; i < sess.length; i++)
2165 JMenuItem sessit = new JMenuItem();
2166 sessit.setText(sess[i]);
2167 sessit.setToolTipText(MessageManager
2168 .formatMessage("label.connect_to_session", new Object[]
2170 final Desktop dsktp = this;
2171 final String mysesid = sess[i];
2172 sessit.addActionListener(new ActionListener()
2176 public void actionPerformed(ActionEvent e)
2178 if (dsktp.v_client == null)
2180 Thread rthr = new Thread(new Runnable()
2186 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2187 dsktp.setupVamsasConnectedGui();
2188 dsktp.v_client.initial_update();
2196 VamsasStMenu.add(sessit);
2198 // don't show an empty menu.
2199 VamsasStMenu.setVisible(sess.length > 0);
2204 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2205 VamsasStMenu.removeAll();
2206 VamsasStMenu.setVisible(false);
2211 // Not interested in the content. Just hide ourselves.
2212 VamsasStMenu.setVisible(false);
2217 public void vamsasSave_actionPerformed(ActionEvent e)
2219 if (v_client != null)
2221 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2222 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2225 chooser.setFileView(new JalviewFileView());
2226 chooser.setDialogTitle(MessageManager
2227 .getString("label.save_vamsas_document_archive"));
2229 int value = chooser.showSaveDialog(this);
2231 if (value == JalviewFileChooser.APPROVE_OPTION)
2233 java.io.File choice = chooser.getSelectedFile();
2234 JPanel progpanel = addProgressPanel(MessageManager
2235 .formatMessage("label.saving_vamsas_doc", new Object[]
2236 { choice.getName() }));
2237 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2238 String warnmsg = null;
2239 String warnttl = null;
2242 v_client.vclient.storeDocument(choice);
2245 warnttl = "Serious Problem saving Vamsas Document";
2246 warnmsg = ex.toString();
2247 jalview.bin.Cache.log
2248 .error("Error Whilst saving document to " + choice, ex);
2250 } catch (Exception ex)
2252 warnttl = "Problem saving Vamsas Document.";
2253 warnmsg = ex.toString();
2254 jalview.bin.Cache.log.warn(
2255 "Exception Whilst saving document to " + choice, ex);
2258 removeProgressPanel(progpanel);
2259 if (warnmsg != null)
2261 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2263 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2269 JPanel vamUpdate = null;
2272 * hide vamsas user gui bits when a vamsas document event is being handled.
2275 * true to hide gui, false to reveal gui
2277 public void setVamsasUpdate(boolean b)
2279 Cache.log.debug("Setting gui for Vamsas update "
2280 + (b ? "in progress" : "finished"));
2282 if (vamUpdate != null)
2284 this.removeProgressPanel(vamUpdate);
2288 vamUpdate = this.addProgressPanel(
2289 MessageManager.getString("label.updating_vamsas_session"));
2291 vamsasStart.setVisible(!b);
2292 vamsasStop.setVisible(!b);
2293 vamsasSave.setVisible(!b);
2296 public JInternalFrame[] getAllFrames()
2298 return desktop.getAllFrames();
2302 * Checks the given url to see if it gives a response indicating that the user
2303 * should be informed of a new questionnaire.
2307 public void checkForQuestionnaire(String url)
2309 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2310 // javax.swing.SwingUtilities.invokeLater(jvq);
2311 new Thread(jvq).start();
2314 public void checkURLLinks()
2316 // Thread off the URL link checker
2317 addDialogThread(new Runnable()
2322 if (Cache.getDefault("CHECKURLLINKS", true))
2324 // check what the actual links are - if it's just the default don't
2325 // bother with the warning
2326 List<String> links = Preferences.sequenceUrlLinks
2329 // only need to check links if there is one with a
2330 // SEQUENCE_ID which is not the default EMBL_EBI link
2331 ListIterator<String> li = links.listIterator();
2332 boolean check = false;
2333 List<JLabel> urls = new ArrayList<>();
2334 while (li.hasNext())
2336 String link = li.next();
2337 if (link.contains(SEQUENCE_ID)
2338 && !UrlConstants.isDefaultString(link))
2341 int barPos = link.indexOf("|");
2342 String urlMsg = barPos == -1 ? link
2343 : link.substring(0, barPos) + ": "
2344 + link.substring(barPos + 1);
2345 urls.add(new JLabel(urlMsg));
2353 // ask user to check in case URL links use old style tokens
2354 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2355 JPanel msgPanel = new JPanel();
2356 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2357 msgPanel.add(Box.createVerticalGlue());
2358 JLabel msg = new JLabel(MessageManager
2359 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2360 JLabel msg2 = new JLabel(MessageManager
2361 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2363 for (JLabel url : urls)
2369 final JCheckBox jcb = new JCheckBox(
2370 MessageManager.getString("label.do_not_display_again"));
2371 jcb.addActionListener(new ActionListener()
2374 public void actionPerformed(ActionEvent e)
2376 // update Cache settings for "don't show this again"
2377 boolean showWarningAgain = !jcb.isSelected();
2378 Cache.setProperty("CHECKURLLINKS",
2379 Boolean.valueOf(showWarningAgain).toString());
2384 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2386 .getString("label.SEQUENCE_ID_no_longer_used"),
2387 JvOptionPane.WARNING_MESSAGE);
2394 * Proxy class for JDesktopPane which optionally displays the current memory
2395 * usage and highlights the desktop area with a red bar if free memory runs
2400 public class MyDesktopPane extends JDesktopPane implements Runnable
2403 private static final float ONE_MB = 1048576f;
2405 boolean showMemoryUsage = false;
2409 java.text.NumberFormat df;
2411 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2414 public MyDesktopPane(boolean showMemoryUsage)
2416 showMemoryUsage(showMemoryUsage);
2419 public void showMemoryUsage(boolean showMemory)
2421 this.showMemoryUsage = showMemory;
2424 Thread worker = new Thread(this);
2430 public boolean isShowMemoryUsage()
2432 return showMemoryUsage;
2438 df = java.text.NumberFormat.getNumberInstance();
2439 df.setMaximumFractionDigits(2);
2440 runtime = Runtime.getRuntime();
2442 while (showMemoryUsage)
2446 maxMemory = runtime.maxMemory() / ONE_MB;
2447 allocatedMemory = runtime.totalMemory() / ONE_MB;
2448 freeMemory = runtime.freeMemory() / ONE_MB;
2449 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2451 percentUsage = (totalFreeMemory / maxMemory) * 100;
2453 // if (percentUsage < 20)
2455 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2457 // instance.set.setBorder(border1);
2460 // sleep after showing usage
2462 } catch (Exception ex)
2464 ex.printStackTrace();
2470 public void paintComponent(Graphics g)
2472 if (showMemoryUsage && g != null && df != null)
2474 if (percentUsage < 20)
2476 g.setColor(Color.red);
2478 FontMetrics fm = g.getFontMetrics();
2481 g.drawString(MessageManager.formatMessage("label.memory_stats",
2483 { df.format(totalFreeMemory), df.format(maxMemory),
2484 df.format(percentUsage) }),
2485 10, getHeight() - fm.getHeight());
2493 * Accessor method to quickly get all the AlignmentFrames loaded.
2495 * @return an array of AlignFrame, or null if none found
2497 public static AlignFrame[] getAlignFrames()
2499 if (Jalview.isHeadlessMode())
2501 // Desktop.desktop is null in headless mode
2502 return new AlignFrame[] { Jalview.currentAlignFrame };
2505 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2511 List<AlignFrame> avp = new ArrayList<>();
2513 for (int i = frames.length - 1; i > -1; i--)
2515 if (frames[i] instanceof AlignFrame)
2517 avp.add((AlignFrame) frames[i]);
2519 else if (frames[i] instanceof SplitFrame)
2522 * Also check for a split frame containing an AlignFrame
2524 GSplitFrame sf = (GSplitFrame) frames[i];
2525 if (sf.getTopFrame() instanceof AlignFrame)
2527 avp.add((AlignFrame) sf.getTopFrame());
2529 if (sf.getBottomFrame() instanceof AlignFrame)
2531 avp.add((AlignFrame) sf.getBottomFrame());
2535 if (avp.size() == 0)
2539 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2544 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2548 public GStructureViewer[] getJmols()
2550 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2556 List<GStructureViewer> avp = new ArrayList<>();
2558 for (int i = frames.length - 1; i > -1; i--)
2560 if (frames[i] instanceof AppJmol)
2562 GStructureViewer af = (GStructureViewer) frames[i];
2566 if (avp.size() == 0)
2570 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2575 * Add Groovy Support to Jalview
2578 public void groovyShell_actionPerformed()
2582 openGroovyConsole();
2583 } catch (Exception ex)
2585 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2586 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2588 MessageManager.getString("label.couldnt_create_groovy_shell"),
2589 MessageManager.getString("label.groovy_support_failed"),
2590 JvOptionPane.ERROR_MESSAGE);
2595 * Open the Groovy console
2597 void openGroovyConsole()
2599 if (groovyConsole == null)
2601 groovyConsole = new groovy.ui.Console();
2602 groovyConsole.setVariable("Jalview", this);
2603 groovyConsole.run();
2606 * We allow only one console at a time, so that AlignFrame menu option
2607 * 'Calculate | Run Groovy script' is unambiguous.
2608 * Disable 'Groovy Console', and enable 'Run script', when the console is
2609 * opened, and the reverse when it is closed
2611 Window window = (Window) groovyConsole.getFrame();
2612 window.addWindowListener(new WindowAdapter()
2615 public void windowClosed(WindowEvent e)
2618 * rebind CMD-Q from Groovy Console to Jalview Quit
2621 enableExecuteGroovy(false);
2627 * show Groovy console window (after close and reopen)
2629 ((Window) groovyConsole.getFrame()).setVisible(true);
2632 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2633 * and disable opening a second console
2635 enableExecuteGroovy(true);
2639 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2640 * binding when opened
2642 protected void addQuitHandler()
2644 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2645 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2646 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2648 getRootPane().getActionMap().put("Quit", new AbstractAction()
2651 public void actionPerformed(ActionEvent e)
2659 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2662 * true if Groovy console is open
2664 public void enableExecuteGroovy(boolean enabled)
2667 * disable opening a second Groovy console
2668 * (or re-enable when the console is closed)
2670 groovyShell.setEnabled(!enabled);
2672 AlignFrame[] alignFrames = getAlignFrames();
2673 if (alignFrames != null)
2675 for (AlignFrame af : alignFrames)
2677 af.setGroovyEnabled(enabled);
2683 * Progress bars managed by the IProgressIndicator method.
2685 private Hashtable<Long, JPanel> progressBars;
2687 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2692 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2695 public void setProgressBar(String message, long id)
2697 if (progressBars == null)
2699 progressBars = new Hashtable<>();
2700 progressBarHandlers = new Hashtable<>();
2703 if (progressBars.get(new Long(id)) != null)
2705 JPanel panel = progressBars.remove(new Long(id));
2706 if (progressBarHandlers.contains(new Long(id)))
2708 progressBarHandlers.remove(new Long(id));
2710 removeProgressPanel(panel);
2714 progressBars.put(new Long(id), addProgressPanel(message));
2721 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2722 * jalview.gui.IProgressIndicatorHandler)
2725 public void registerHandler(final long id,
2726 final IProgressIndicatorHandler handler)
2728 if (progressBarHandlers == null
2729 || !progressBars.containsKey(new Long(id)))
2731 throw new Error(MessageManager.getString(
2732 "error.call_setprogressbar_before_registering_handler"));
2734 progressBarHandlers.put(new Long(id), handler);
2735 final JPanel progressPanel = progressBars.get(new Long(id));
2736 if (handler.canCancel())
2738 JButton cancel = new JButton(
2739 MessageManager.getString("action.cancel"));
2740 final IProgressIndicator us = this;
2741 cancel.addActionListener(new ActionListener()
2745 public void actionPerformed(ActionEvent e)
2747 handler.cancelActivity(id);
2748 us.setProgressBar(MessageManager
2749 .formatMessage("label.cancelled_params", new Object[]
2750 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2754 progressPanel.add(cancel, BorderLayout.EAST);
2760 * @return true if any progress bars are still active
2763 public boolean operationInProgress()
2765 if (progressBars != null && progressBars.size() > 0)
2773 * This will return the first AlignFrame holding the given viewport instance.
2774 * It will break if there are more than one AlignFrames viewing a particular
2778 * @return alignFrame for viewport
2780 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2782 if (desktop != null)
2784 AlignmentPanel[] aps = getAlignmentPanels(
2785 viewport.getSequenceSetId());
2786 for (int panel = 0; aps != null && panel < aps.length; panel++)
2788 if (aps[panel] != null && aps[panel].av == viewport)
2790 return aps[panel].alignFrame;
2797 public VamsasApplication getVamsasApplication()
2804 * flag set if jalview GUI is being operated programmatically
2806 private boolean inBatchMode = false;
2809 * check if jalview GUI is being operated programmatically
2811 * @return inBatchMode
2813 public boolean isInBatchMode()
2819 * set flag if jalview GUI is being operated programmatically
2821 * @param inBatchMode
2823 public void setInBatchMode(boolean inBatchMode)
2825 this.inBatchMode = inBatchMode;
2828 public void startServiceDiscovery()
2830 startServiceDiscovery(false);
2833 public void startServiceDiscovery(boolean blocking)
2835 boolean alive = true;
2836 Thread t0 = null, t1 = null, t2 = null;
2837 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2840 // todo: changesupport handlers need to be transferred
2841 if (discoverer == null)
2843 discoverer = new jalview.ws.jws1.Discoverer();
2844 // register PCS handler for desktop.
2845 discoverer.addPropertyChangeListener(changeSupport);
2847 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2848 // until we phase out completely
2849 (t0 = new Thread(discoverer)).start();
2852 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2854 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2855 .startDiscoverer(changeSupport);
2859 // TODO: do rest service discovery
2868 } catch (Exception e)
2871 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2872 || (t3 != null && t3.isAlive())
2873 || (t0 != null && t0.isAlive());
2879 * called to check if the service discovery process completed successfully.
2883 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2885 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2887 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2888 .getErrorMessages();
2891 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2893 if (serviceChangedDialog == null)
2895 // only run if we aren't already displaying one of these.
2896 addDialogThread(serviceChangedDialog = new Runnable()
2903 * JalviewDialog jd =new JalviewDialog() {
2905 * @Override protected void cancelPressed() { // TODO
2906 * Auto-generated method stub
2908 * }@Override protected void okPressed() { // TODO
2909 * Auto-generated method stub
2911 * }@Override protected void raiseClosed() { // TODO
2912 * Auto-generated method stub
2914 * } }; jd.initDialogFrame(new
2915 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2916 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2917 * + " or mis-configured HTTP proxy settings.<br/>" +
2918 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2920 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2921 * ), true, true, "Web Service Configuration Problem", 450,
2924 * jd.waitForInput();
2926 JvOptionPane.showConfirmDialog(Desktop.desktop,
2927 new JLabel("<html><table width=\"450\"><tr><td>"
2928 + ermsg + "</td></tr></table>"
2929 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2930 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2931 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2932 + " Tools->Preferences dialog box to change them.</p></html>"),
2933 "Web Service Configuration Problem",
2934 JvOptionPane.DEFAULT_OPTION,
2935 JvOptionPane.ERROR_MESSAGE);
2936 serviceChangedDialog = null;
2945 "Errors reported by JABA discovery service. Check web services preferences.\n"
2952 private Runnable serviceChangedDialog = null;
2955 * start a thread to open a URL in the configured browser. Pops up a warning
2956 * dialog to the user if there is an exception when calling out to the browser
2961 public static void showUrl(final String url)
2963 showUrl(url, Desktop.instance);
2967 * Like showUrl but allows progress handler to be specified
2971 * (null) or object implementing IProgressIndicator
2973 public static void showUrl(final String url,
2974 final IProgressIndicator progress)
2976 new Thread(new Runnable()
2983 if (progress != null)
2985 progress.setProgressBar(MessageManager
2986 .formatMessage("status.opening_params", new Object[]
2987 { url }), this.hashCode());
2989 jalview.util.BrowserLauncher.openURL(url);
2990 } catch (Exception ex)
2992 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2994 .getString("label.web_browser_not_found_unix"),
2995 MessageManager.getString("label.web_browser_not_found"),
2996 JvOptionPane.WARNING_MESSAGE);
2998 ex.printStackTrace();
3000 if (progress != null)
3002 progress.setProgressBar(null, this.hashCode());
3008 public static WsParamSetManager wsparamManager = null;
3010 public static ParamManager getUserParameterStore()
3012 if (wsparamManager == null)
3014 wsparamManager = new WsParamSetManager();
3016 return wsparamManager;
3020 * static hyperlink handler proxy method for use by Jalview's internal windows
3024 public static void hyperlinkUpdate(HyperlinkEvent e)
3026 if (e.getEventType() == EventType.ACTIVATED)
3031 url = e.getURL().toString();
3032 Desktop.showUrl(url);
3033 } catch (Exception x)
3037 if (Cache.log != null)
3039 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3044 "Couldn't handle string " + url + " as a URL.");
3047 // ignore any exceptions due to dud links.
3054 * single thread that handles display of dialogs to user.
3056 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3059 * flag indicating if dialogExecutor should try to acquire a permit
3061 private volatile boolean dialogPause = true;
3066 private java.util.concurrent.Semaphore block = new Semaphore(0);
3068 private static groovy.ui.Console groovyConsole;
3071 * add another dialog thread to the queue
3075 public void addDialogThread(final Runnable prompter)
3077 dialogExecutor.submit(new Runnable()
3087 } catch (InterruptedException x)
3092 if (instance == null)
3098 SwingUtilities.invokeAndWait(prompter);
3099 } catch (Exception q)
3101 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3107 public void startDialogQueue()
3109 // set the flag so we don't pause waiting for another permit and semaphore
3110 // the current task to begin
3111 dialogPause = false;
3116 protected void snapShotWindow_actionPerformed(ActionEvent e)
3120 ImageMaker im = new jalview.util.ImageMaker(
3121 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3122 getHeight(), of = new File("Jalview_snapshot"
3123 + System.currentTimeMillis() + ".eps"),
3124 "View of desktop", null, 0, false);
3127 paintAll(im.getGraphics());
3129 } catch (Exception q)
3131 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3135 Cache.log.info("Successfully written snapshot to file "
3136 + of.getAbsolutePath());
3140 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3141 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3142 * and location last time the view was expanded (if any). However it does not
3143 * remember the split pane divider location - this is set to match the
3144 * 'exploding' frame.
3148 public void explodeViews(SplitFrame sf)
3150 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3151 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3152 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3154 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3156 int viewCount = topPanels.size();
3163 * Processing in reverse order works, forwards order leaves the first panels
3164 * not visible. I don't know why!
3166 for (int i = viewCount - 1; i >= 0; i--)
3169 * Make new top and bottom frames. These take over the respective
3170 * AlignmentPanel objects, including their AlignmentViewports, so the
3171 * cdna/protein relationships between the viewports is carried over to the
3174 * explodedGeometry holds the (x, y) position of the previously exploded
3175 * SplitFrame, and the (width, height) of the AlignFrame component
3177 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3178 AlignFrame newTopFrame = new AlignFrame(topPanel);
3179 newTopFrame.setSize(oldTopFrame.getSize());
3180 newTopFrame.setVisible(true);
3181 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3182 .getExplodedGeometry();
3183 if (geometry != null)
3185 newTopFrame.setSize(geometry.getSize());
3188 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3189 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3190 newBottomFrame.setSize(oldBottomFrame.getSize());
3191 newBottomFrame.setVisible(true);
3192 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3193 .getExplodedGeometry();
3194 if (geometry != null)
3196 newBottomFrame.setSize(geometry.getSize());
3199 topPanel.av.setGatherViewsHere(false);
3200 bottomPanel.av.setGatherViewsHere(false);
3201 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3203 if (geometry != null)
3205 splitFrame.setLocation(geometry.getLocation());
3207 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3211 * Clear references to the panels (now relocated in the new SplitFrames)
3212 * before closing the old SplitFrame.
3215 bottomPanels.clear();
3220 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3221 * back into the given SplitFrame as additional views. Note that the gathered
3222 * frames may themselves have multiple views.
3226 public void gatherViews(GSplitFrame source)
3229 * special handling of explodedGeometry for a view within a SplitFrame: - it
3230 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3231 * height) of the AlignFrame component
3233 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3234 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3235 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3236 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3237 myBottomFrame.viewport
3238 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3239 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3240 myTopFrame.viewport.setGatherViewsHere(true);
3241 myBottomFrame.viewport.setGatherViewsHere(true);
3242 String topViewId = myTopFrame.viewport.getSequenceSetId();
3243 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3245 JInternalFrame[] frames = desktop.getAllFrames();
3246 for (JInternalFrame frame : frames)
3248 if (frame instanceof SplitFrame && frame != source)
3250 SplitFrame sf = (SplitFrame) frame;
3251 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3252 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3253 boolean gatherThis = false;
3254 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3256 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3257 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3258 if (topViewId.equals(topPanel.av.getSequenceSetId())
3259 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3262 topPanel.av.setGatherViewsHere(false);
3263 bottomPanel.av.setGatherViewsHere(false);
3264 topPanel.av.setExplodedGeometry(
3265 new Rectangle(sf.getLocation(), topFrame.getSize()));
3266 bottomPanel.av.setExplodedGeometry(
3267 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3268 myTopFrame.addAlignmentPanel(topPanel, false);
3269 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3275 topFrame.getAlignPanels().clear();
3276 bottomFrame.getAlignPanels().clear();
3283 * The dust settles...give focus to the tab we did this from.
3285 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3288 public static groovy.ui.Console getGroovyConsole()
3290 return groovyConsole;
3293 public static void transferFromDropTarget(List<String> files,
3294 List<DataSourceType> protocols, DropTargetDropEvent evt,
3295 Transferable t) throws Exception
3298 DataFlavor uriListFlavor = new DataFlavor(
3299 "text/uri-list;class=java.lang.String");
3300 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3302 // Works on Windows and MacOSX
3303 Cache.log.debug("Drop handled as javaFileListFlavor");
3304 for (Object file : (List) t
3305 .getTransferData(DataFlavor.javaFileListFlavor))
3307 files.add(((File) file).toString());
3308 protocols.add(DataSourceType.FILE);
3313 // Unix like behaviour
3314 boolean added = false;
3316 if (t.isDataFlavorSupported(uriListFlavor))
3318 Cache.log.debug("Drop handled as uriListFlavor");
3319 // This is used by Unix drag system
3320 data = (String) t.getTransferData(uriListFlavor);
3324 // fallback to text: workaround - on OSX where there's a JVM bug
3325 Cache.log.debug("standard URIListFlavor failed. Trying text");
3326 // try text fallback
3327 data = (String) t.getTransferData(
3328 new DataFlavor("text/plain;class=java.lang.String"));
3329 if (Cache.log.isDebugEnabled())
3331 Cache.log.debug("fallback returned " + data);
3334 while (protocols.size() < files.size())
3336 Cache.log.debug("Adding missing FILE protocol for "
3337 + files.get(protocols.size()));
3338 protocols.add(DataSourceType.FILE);
3340 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3341 data, "\r\n"); st.hasMoreTokens();)
3344 String s = st.nextToken();
3345 if (s.startsWith("#"))
3347 // the line is a comment (as per the RFC 2483)
3350 java.net.URI uri = new java.net.URI(s);
3351 if (uri.getScheme().toLowerCase().startsWith("http"))
3353 protocols.add(DataSourceType.URL);
3354 files.add(uri.toString());
3358 // otherwise preserve old behaviour: catch all for file objects
3359 java.io.File file = new java.io.File(uri);
3360 protocols.add(DataSourceType.FILE);
3361 files.add(file.toString());
3364 if (Cache.log.isDebugEnabled())
3366 if (data == null || !added)
3369 "Couldn't resolve drop data. Here are the supported flavors:");
3370 for (DataFlavor fl : t.getTransferDataFlavors())
3373 "Supported transfer dataflavor: " + fl.toString());
3374 Object df = t.getTransferData(fl);
3377 Cache.log.debug("Retrieves: " + df);
3381 Cache.log.debug("Retrieved nothing");
3390 * Sets the Preferences property for experimental features to True or False
3391 * depending on the state of the controlling menu item
3394 protected void showExperimental_actionPerformed(boolean selected)
3396 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));