2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.FocusEvent;
72 import java.awt.event.FocusListener;
73 import java.awt.event.KeyEvent;
74 import java.awt.event.MouseAdapter;
75 import java.awt.event.MouseEvent;
76 import java.awt.event.WindowAdapter;
77 import java.awt.event.WindowEvent;
78 import java.beans.PropertyChangeEvent;
79 import java.beans.PropertyChangeListener;
80 import java.io.BufferedInputStream;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Hashtable;
87 import java.util.List;
88 import java.util.ListIterator;
89 import java.util.StringTokenizer;
90 import java.util.Vector;
91 import java.util.concurrent.ExecutorService;
92 import java.util.concurrent.Executors;
93 import java.util.concurrent.Semaphore;
95 import javax.swing.AbstractAction;
96 import javax.swing.Box;
97 import javax.swing.BoxLayout;
98 import javax.swing.DefaultDesktopManager;
99 import javax.swing.DesktopManager;
100 import javax.swing.JButton;
101 import javax.swing.JCheckBox;
102 import javax.swing.JComboBox;
103 import javax.swing.JComponent;
104 import javax.swing.JDesktopPane;
105 import javax.swing.JFrame;
106 import javax.swing.JInternalFrame;
107 import javax.swing.JLabel;
108 import javax.swing.JMenuItem;
109 import javax.swing.JPanel;
110 import javax.swing.JPopupMenu;
111 import javax.swing.JProgressBar;
112 import javax.swing.KeyStroke;
113 import javax.swing.SwingUtilities;
114 import javax.swing.event.HyperlinkEvent;
115 import javax.swing.event.HyperlinkEvent.EventType;
116 import javax.swing.event.InternalFrameAdapter;
117 import javax.swing.event.InternalFrameEvent;
118 import javax.swing.event.MenuEvent;
119 import javax.swing.event.MenuListener;
126 * @version $Revision: 1.155 $
128 public class Desktop extends jalview.jbgui.GDesktop implements
129 DropTargetListener, ClipboardOwner, IProgressIndicator,
130 jalview.api.StructureSelectionManagerProvider
132 private static int DEFAULT_MIN_WIDTH = 300;
134 private static int DEFAULT_MIN_HEIGHT = 250;
136 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
138 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
141 * news reader - null if it was never started.
143 private BlogReader jvnews = null;
145 private File projectFile;
149 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
151 public void addJalviewPropertyChangeListener(
152 PropertyChangeListener listener)
154 changeSupport.addJalviewPropertyChangeListener(listener);
158 * @param propertyName
160 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
161 * java.beans.PropertyChangeListener)
163 public void addJalviewPropertyChangeListener(String propertyName,
164 PropertyChangeListener listener)
166 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
170 * @param propertyName
172 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
173 * java.beans.PropertyChangeListener)
175 public void removeJalviewPropertyChangeListener(String propertyName,
176 PropertyChangeListener listener)
178 changeSupport.removeJalviewPropertyChangeListener(propertyName,
182 /** Singleton Desktop instance */
183 public static Desktop instance;
185 public static MyDesktopPane desktop;
187 static int openFrameCount = 0;
189 static final int xOffset = 30;
191 static final int yOffset = 30;
193 public static jalview.ws.jws1.Discoverer discoverer;
195 public static Object[] jalviewClipboard;
197 public static boolean internalCopy = false;
199 static int fileLoadingCount = 0;
201 class MyDesktopManager implements DesktopManager
204 private DesktopManager delegate;
206 public MyDesktopManager(DesktopManager delegate)
208 this.delegate = delegate;
212 public void activateFrame(JInternalFrame f)
216 delegate.activateFrame(f);
217 } catch (NullPointerException npe)
219 Point p = getMousePosition();
220 instance.showPasteMenu(p.x, p.y);
225 public void beginDraggingFrame(JComponent f)
227 delegate.beginDraggingFrame(f);
231 public void beginResizingFrame(JComponent f, int direction)
233 delegate.beginResizingFrame(f, direction);
237 public void closeFrame(JInternalFrame f)
239 delegate.closeFrame(f);
243 public void deactivateFrame(JInternalFrame f)
245 delegate.deactivateFrame(f);
249 public void deiconifyFrame(JInternalFrame f)
251 delegate.deiconifyFrame(f);
255 public void dragFrame(JComponent f, int newX, int newY)
261 delegate.dragFrame(f, newX, newY);
265 public void endDraggingFrame(JComponent f)
267 delegate.endDraggingFrame(f);
271 public void endResizingFrame(JComponent f)
273 delegate.endResizingFrame(f);
277 public void iconifyFrame(JInternalFrame f)
279 delegate.iconifyFrame(f);
283 public void maximizeFrame(JInternalFrame f)
285 delegate.maximizeFrame(f);
289 public void minimizeFrame(JInternalFrame f)
291 delegate.minimizeFrame(f);
295 public void openFrame(JInternalFrame f)
297 delegate.openFrame(f);
301 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
308 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
312 public void setBoundsForFrame(JComponent f, int newX, int newY,
313 int newWidth, int newHeight)
315 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
318 // All other methods, simply delegate
323 * Creates a new Desktop object.
328 * A note to implementors. It is ESSENTIAL that any activities that might
329 * block are spawned off as threads rather than waited for during this
333 doVamsasClientCheck();
335 doConfigureStructurePrefs();
336 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
337 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
338 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
340 boolean showjconsole = jalview.bin.Cache.getDefault(
341 "SHOW_JAVA_CONSOLE", false);
342 desktop = new MyDesktopPane(selmemusage);
343 if (Platform.isAMac())
345 desktop.setDoubleBuffered(false);
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(new MyDesktopManager(
360 new DefaultDesktopManager()));
362 Rectangle dims = getLastKnownDimensions("");
369 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
370 setBounds((screenSize.width - 900) / 2,
371 (screenSize.height - 650) / 2, 900, 650);
373 jconsole = new Console(this, showjconsole);
374 // add essential build information
375 jconsole.setHeader("Jalview Version: "
376 + jalview.bin.Cache.getProperty("VERSION") + "\n"
377 + "Jalview Installation: "
378 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
379 + "\n" + "Build Date: "
380 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
381 + "Java version: " + System.getProperty("java.version") + "\n"
382 + System.getProperty("os.arch") + " "
383 + System.getProperty("os.name") + " "
384 + System.getProperty("os.version"));
386 showConsole(showjconsole);
388 showNews.setVisible(false);
390 experimentalFeatures.setSelected(showExperimental());
392 getIdentifiersOrgData();
396 this.addWindowListener(new WindowAdapter()
399 public void windowClosing(WindowEvent evt)
406 this.addMouseListener(ma = new MouseAdapter()
409 public void mousePressed(MouseEvent evt)
411 if (evt.isPopupTrigger()) // Mac
413 showPasteMenu(evt.getX(), evt.getY());
418 public void mouseReleased(MouseEvent evt)
420 if (evt.isPopupTrigger()) // Windows
422 showPasteMenu(evt.getX(), evt.getY());
426 desktop.addMouseListener(ma);
428 this.addFocusListener(new FocusListener()
432 public void focusLost(FocusEvent e)
434 // TODO Auto-generated method stub
439 public void focusGained(FocusEvent e)
441 Cache.log.debug("Relaying windows after focus gain");
442 // make sure that we sort windows properly after we gain focus
443 instance.relayerWindows();
446 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
447 // Spawn a thread that shows the splashscreen
448 SwingUtilities.invokeLater(new Runnable()
457 // Thread off a new instance of the file chooser - this reduces the time it
458 // takes to open it later on.
459 new Thread(new Runnable()
464 Cache.log.debug("Filechooser init thread started.");
465 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
466 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
468 Cache.log.debug("Filechooser init thread finished.");
471 // Add the service change listener
472 changeSupport.addJalviewPropertyChangeListener("services",
473 new PropertyChangeListener()
477 public void propertyChange(PropertyChangeEvent evt)
479 Cache.log.debug("Firing service changed event for "
480 + evt.getNewValue());
481 JalviewServicesChanged(evt);
488 * Answers true if user preferences to enable experimental features is True
493 public boolean showExperimental()
495 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
496 Boolean.FALSE.toString());
497 return Boolean.valueOf(experimental).booleanValue();
500 public void doConfigureStructurePrefs()
502 // configure services
503 StructureSelectionManager ssm = StructureSelectionManager
504 .getStructureSelectionManager(this);
505 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
507 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
508 Preferences.ADD_TEMPFACT_ANN, true));
509 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
510 Preferences.STRUCT_FROM_PDB, true));
511 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
512 Preferences.USE_RNAVIEW, true));
516 ssm.setAddTempFacAnnot(false);
517 ssm.setProcessSecondaryStructure(false);
518 ssm.setSecStructServices(false);
522 public void checkForNews()
524 final Desktop me = this;
525 // Thread off the news reader, in case there are connection problems.
526 addDialogThread(new Runnable()
531 Cache.log.debug("Starting news thread.");
533 jvnews = new BlogReader(me);
534 showNews.setVisible(true);
535 Cache.log.debug("Completed news thread.");
540 public void getIdentifiersOrgData()
542 // Thread off the identifiers fetcher
543 addDialogThread(new Runnable()
548 Cache.log.debug("Downloading data from identifiers.org");
549 UrlDownloadClient client = new UrlDownloadClient();
552 client.download(IdOrgSettings.getUrl(),
553 IdOrgSettings.getDownloadLocation());
554 } catch (IOException e)
556 Cache.log.debug("Exception downloading identifiers.org data"
564 protected void showNews_actionPerformed(ActionEvent e)
566 showNews(showNews.isSelected());
569 void showNews(boolean visible)
572 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
573 showNews.setSelected(visible);
574 if (visible && !jvnews.isVisible())
576 new Thread(new Runnable()
581 long now = System.currentTimeMillis();
582 Desktop.instance.setProgressBar(
583 MessageManager.getString("status.refreshing_news"), now);
584 jvnews.refreshNews();
585 Desktop.instance.setProgressBar(null, now);
594 * recover the last known dimensions for a jalview window
597 * - empty string is desktop, all other windows have unique prefix
598 * @return null or last known dimensions scaled to current geometry (if last
599 * window geom was known)
601 Rectangle getLastKnownDimensions(String windowName)
603 // TODO: lock aspect ratio for scaling desktop Bug #0058199
604 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
605 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
606 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
607 String width = jalview.bin.Cache.getProperty(windowName
609 String height = jalview.bin.Cache.getProperty(windowName
611 if ((x != null) && (y != null) && (width != null) && (height != null))
613 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
614 .parseInt(width), ih = Integer.parseInt(height);
615 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
617 // attempt #1 - try to cope with change in screen geometry - this
618 // version doesn't preserve original jv aspect ratio.
619 // take ratio of current screen size vs original screen size.
620 double sw = ((1f * screenSize.width) / (1f * Integer
621 .parseInt(jalview.bin.Cache
622 .getProperty("SCREENGEOMETRY_WIDTH"))));
623 double sh = ((1f * screenSize.height) / (1f * Integer
624 .parseInt(jalview.bin.Cache
625 .getProperty("SCREENGEOMETRY_HEIGHT"))));
626 // rescale the bounds depending upon the current screen geometry.
627 ix = (int) (ix * sw);
628 iw = (int) (iw * sw);
629 iy = (int) (iy * sh);
630 ih = (int) (ih * sh);
631 while (ix >= screenSize.width)
633 jalview.bin.Cache.log
634 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
635 ix -= screenSize.width;
637 while (iy >= screenSize.height)
639 jalview.bin.Cache.log
640 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
641 iy -= screenSize.height;
643 jalview.bin.Cache.log.debug("Got last known dimensions for "
644 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
647 // return dimensions for new instance
648 return new Rectangle(ix, iy, iw, ih);
653 private void doVamsasClientCheck()
655 if (jalview.bin.Cache.vamsasJarsPresent())
657 setupVamsasDisconnectedGui();
658 VamsasMenu.setVisible(true);
659 final Desktop us = this;
660 VamsasMenu.addMenuListener(new MenuListener()
662 // this listener remembers when the menu was first selected, and
663 // doesn't rebuild the session list until it has been cleared and
665 boolean refresh = true;
668 public void menuCanceled(MenuEvent e)
674 public void menuDeselected(MenuEvent e)
680 public void menuSelected(MenuEvent e)
684 us.buildVamsasStMenu();
689 vamsasStart.setVisible(true);
693 void showPasteMenu(int x, int y)
695 JPopupMenu popup = new JPopupMenu();
696 JMenuItem item = new JMenuItem(
697 MessageManager.getString("label.paste_new_window"));
698 item.addActionListener(new ActionListener()
701 public void actionPerformed(ActionEvent evt)
708 popup.show(this, x, y);
715 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
716 Transferable contents = c.getContents(this);
718 if (contents != null)
720 String file = (String) contents
721 .getTransferData(DataFlavor.stringFlavor);
723 FileFormatI format = new IdentifyFile().identify(file,
724 DataSourceType.PASTE);
726 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
729 } catch (Exception ex)
732 .println("Unable to paste alignment from system clipboard:\n"
738 * Adds and opens the given frame to the desktop
749 public static synchronized void addInternalFrame(
750 final JInternalFrame frame, String title, int w, int h)
752 addInternalFrame(frame, title, true, w, h, true);
756 * Add an internal frame to the Jalview desktop
763 * When true, display frame immediately, otherwise, caller must call
764 * setVisible themselves.
770 public static synchronized void addInternalFrame(
771 final JInternalFrame frame, String title, boolean makeVisible,
774 addInternalFrame(frame, title, makeVisible, w, h, true);
778 * Add an internal frame to the Jalview desktop and make it visible
791 public static synchronized void addInternalFrame(
792 final JInternalFrame frame, String title, int w, int h,
795 addInternalFrame(frame, title, true, w, h, resizable);
799 * Add an internal frame to the Jalview desktop
806 * When true, display frame immediately, otherwise, caller must call
807 * setVisible themselves.
815 public static synchronized void addInternalFrame(
816 final JInternalFrame frame, String title, boolean makeVisible,
817 int w, int h, boolean resizable)
820 // TODO: allow callers to determine X and Y position of frame (eg. via
822 // TODO: consider fixing method to update entries in the window submenu with
823 // the current window title
825 frame.setTitle(title);
826 if (frame.getWidth() < 1 || frame.getHeight() < 1)
830 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
831 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
832 // IF JALVIEW IS RUNNING HEADLESS
833 // ///////////////////////////////////////////////
835 || (System.getProperty("java.awt.headless") != null && System
836 .getProperty("java.awt.headless").equals("true")))
843 frame.setMinimumSize(new Dimension(DEFAULT_MIN_WIDTH,
844 DEFAULT_MIN_HEIGHT));
845 frame.setVisible(makeVisible);
846 frame.setClosable(true);
847 frame.setResizable(resizable);
848 frame.setMaximizable(resizable);
849 frame.setIconifiable(resizable);
850 if (Platform.isAMac())
852 frame.setIconifiable(false);
853 frame.setFrameIcon(null);
854 // frame.setDesktopIcon(null);
855 frame.setDoubleBuffered(false);
857 if (frame.getX() < 1 && frame.getY() < 1)
859 frame.setLocation(xOffset * openFrameCount, yOffset
860 * ((openFrameCount - 1) % 10) + yOffset);
864 * add an entry for the new frame in the Window menu
865 * (and remove it when the frame is closed)
867 final JMenuItem menuItem = new JMenuItem(title);
868 frame.addInternalFrameListener(new InternalFrameAdapter()
871 public void internalFrameActivated(InternalFrameEvent evt)
873 JInternalFrame itf = desktop.getSelectedFrame();
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);
902 JInternalFrame itf = desktop.getSelectedFrame();
906 if (itf instanceof AlignFrame)
908 Jalview.setCurrentAlignFrame((AlignFrame) itf);
915 menuItem.addActionListener(new ActionListener()
918 public void actionPerformed(ActionEvent e)
922 frame.setSelected(true);
923 frame.setIcon(false);
924 } catch (java.beans.PropertyVetoException ex)
933 windowMenu.add(menuItem);
938 frame.setSelected(true);
939 frame.requestFocus();
940 } catch (java.beans.PropertyVetoException ve)
942 } catch (java.lang.ClassCastException cex)
945 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
951 public void lostOwnership(Clipboard clipboard, Transferable contents)
955 Desktop.jalviewClipboard = null;
958 internalCopy = false;
962 public void dragEnter(DropTargetDragEvent evt)
967 public void dragExit(DropTargetEvent evt)
972 public void dragOver(DropTargetDragEvent evt)
977 public void dropActionChanged(DropTargetDragEvent evt)
988 public void drop(DropTargetDropEvent evt)
990 boolean success = true;
991 // JAL-1552 - acceptDrop required before getTransferable call for
992 // Java's Transferable for native dnd
993 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
994 Transferable t = evt.getTransferable();
995 List<String> files = new ArrayList<String>();
996 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
1000 Desktop.transferFromDropTarget(files, protocols, evt, t);
1001 } catch (Exception e)
1003 e.printStackTrace();
1011 for (int i = 0; i < files.size(); i++)
1013 String file = files.get(i).toString();
1014 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
1016 FileFormatI format = null;
1018 if (file.endsWith(".jar"))
1020 format = FileFormat.Jalview;
1025 format = new IdentifyFile().identify(file, protocol);
1028 new FileLoader().LoadFile(file, protocol, format);
1031 } catch (Exception ex)
1036 evt.dropComplete(success); // need this to ensure input focus is properly
1037 // transfered to any new windows created
1047 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1049 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1050 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1051 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1053 chooser.setFileView(new JalviewFileView());
1054 chooser.setDialogTitle(MessageManager
1055 .getString("label.open_local_file"));
1056 chooser.setToolTipText(MessageManager.getString("action.open"));
1058 int value = chooser.showOpenDialog(this);
1060 if (value == JalviewFileChooser.APPROVE_OPTION)
1062 String choice = chooser.getSelectedFile().getPath();
1063 Cache.setProperty("LAST_DIRECTORY", chooser
1064 .getSelectedFile().getParent());
1066 FileFormatI format = chooser.getSelectedFormat();
1069 * Call IdentifyFile to verify the file contains what its extension implies.
1070 * Skip this step for dynamically added file formats, because
1071 * IdentifyFile does not know how to recognise them.
1073 if (FileFormats.getInstance().isIdentifiable(format))
1077 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1078 } catch (FileFormatException e)
1080 // format = null; //??
1084 if (viewport != null)
1086 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1091 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1103 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1105 // This construct allows us to have a wider textfield
1107 JLabel label = new JLabel(
1108 MessageManager.getString("label.input_file_url"));
1109 final JComboBox history = new JComboBox();
1111 JPanel panel = new JPanel(new GridLayout(2, 1));
1114 history.setPreferredSize(new Dimension(400, 20));
1115 history.setEditable(true);
1116 history.addItem("http://www.");
1118 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1122 if (historyItems != null)
1124 st = new StringTokenizer(historyItems, "\t");
1126 while (st.hasMoreTokens())
1128 history.addItem(st.nextElement());
1132 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1133 MessageManager.getString("label.input_alignment_from_url"),
1134 JvOptionPane.OK_CANCEL_OPTION);
1136 if (reply != JvOptionPane.OK_OPTION)
1141 String url = history.getSelectedItem().toString();
1143 if (url.toLowerCase().endsWith(".jar"))
1145 if (viewport != null)
1147 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1148 FileFormat.Jalview);
1152 new FileLoader().LoadFile(url, DataSourceType.URL,
1153 FileFormat.Jalview);
1158 FileFormatI format = null;
1161 format = new IdentifyFile().identify(url, DataSourceType.URL);
1162 } catch (FileFormatException e)
1164 // TODO revise error handling, distinguish between
1165 // URL not found and response not valid
1170 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1171 MessageManager.formatMessage("label.couldnt_locate",
1172 new Object[] { url }), MessageManager
1173 .getString("label.url_not_found"),
1174 JvOptionPane.WARNING_MESSAGE);
1179 if (viewport != null)
1182 .LoadFile(viewport, url, DataSourceType.URL, format);
1186 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1192 * Opens the CutAndPaste window for the user to paste an alignment in to
1195 * - if not null, the pasted alignment is added to the current
1196 * alignment; if null, to a new alignment window
1199 public void inputTextboxMenuItem_actionPerformed(
1200 AlignmentViewPanel viewPanel)
1202 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1203 cap.setForInput(viewPanel);
1204 Desktop.addInternalFrame(cap,
1205 MessageManager.getString("label.cut_paste_alignmen_file"),
1215 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1217 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1218 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1220 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1221 getBounds().y, getWidth(), getHeight()));
1223 if (jconsole != null)
1225 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1226 jconsole.stopConsole();
1230 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1233 if (dialogExecutor != null)
1235 dialogExecutor.shutdownNow();
1237 closeAll_actionPerformed(null);
1239 if (groovyConsole != null)
1241 // suppress a possible repeat prompt to save script
1242 groovyConsole.setDirty(false);
1243 groovyConsole.exit();
1248 private void storeLastKnownDimensions(String string, Rectangle jc)
1250 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1251 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1252 + " height:" + jc.height);
1254 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1255 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1256 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1257 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1267 public void aboutMenuItem_actionPerformed(ActionEvent e)
1269 // StringBuffer message = getAboutMessage(false);
1270 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1272 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1273 new Thread(new Runnable()
1278 new SplashScreen(true);
1283 public StringBuffer getAboutMessage(boolean shortv)
1285 StringBuffer message = new StringBuffer();
1286 message.append("<html>");
1289 message.append("<h1><strong>Version: "
1290 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1291 message.append("<strong>Last Updated: <em>"
1292 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1293 + "</em></strong>");
1299 message.append("<strong>Version "
1300 + jalview.bin.Cache.getProperty("VERSION")
1301 + "; last updated: "
1302 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1305 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1308 message.append("<br>...Checking latest version...</br>");
1310 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1311 .equals(jalview.bin.Cache.getProperty("VERSION")))
1313 boolean red = false;
1314 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1315 .indexOf("automated build") == -1)
1318 // Displayed when code version and jnlp version do not match and code
1319 // version is not a development build
1320 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1323 message.append("<br>!! Version "
1324 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1326 + " is available for download from "
1327 + jalview.bin.Cache.getDefault("www.jalview.org",
1328 "http://www.jalview.org") + " !!");
1331 message.append("</div>");
1334 message.append("<br>Authors: "
1336 .getDefault("AUTHORFNAMES",
1337 "The Jalview Authors (See AUTHORS file for current list)")
1338 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1339 + "<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"
1340 + "<br><br>If you use Jalview, please cite:"
1341 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1342 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1343 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1355 public void documentationMenuItem_actionPerformed(ActionEvent e)
1359 Help.showHelpWindow();
1360 } catch (Exception ex)
1366 public void closeAll_actionPerformed(ActionEvent e)
1368 // TODO show a progress bar while closing?
1369 JInternalFrame[] frames = desktop.getAllFrames();
1370 for (int i = 0; i < frames.length; i++)
1374 frames[i].setClosed(true);
1375 } catch (java.beans.PropertyVetoException ex)
1379 Jalview.setCurrentAlignFrame(null);
1380 System.out.println("ALL CLOSED");
1381 if (v_client != null)
1383 // TODO clear binding to vamsas document objects on close_all
1387 * reset state of singleton objects as appropriate (clear down session state
1388 * when all windows are closed)
1390 StructureSelectionManager ssm = StructureSelectionManager
1391 .getStructureSelectionManager(this);
1400 public void raiseRelated_actionPerformed(ActionEvent e)
1402 reorderAssociatedWindows(false, false);
1406 public void minimizeAssociated_actionPerformed(ActionEvent e)
1408 reorderAssociatedWindows(true, false);
1411 void closeAssociatedWindows()
1413 reorderAssociatedWindows(false, true);
1419 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1423 protected void garbageCollect_actionPerformed(ActionEvent e)
1425 // We simply collect the garbage
1426 jalview.bin.Cache.log.debug("Collecting garbage...");
1428 jalview.bin.Cache.log.debug("Finished garbage collection.");
1435 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1439 protected void showMemusage_actionPerformed(ActionEvent e)
1441 desktop.showMemoryUsage(showMemusage.isSelected());
1448 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1452 protected void showConsole_actionPerformed(ActionEvent e)
1454 showConsole(showConsole.isSelected());
1457 Console jconsole = null;
1460 * control whether the java console is visible or not
1464 void showConsole(boolean selected)
1466 showConsole.setSelected(selected);
1467 // TODO: decide if we should update properties file
1468 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1470 jconsole.setVisible(selected);
1473 void reorderAssociatedWindows(boolean minimize, boolean close)
1475 JInternalFrame[] frames = desktop.getAllFrames();
1476 if (frames == null || frames.length < 1)
1481 AlignmentViewport source = null, target = null;
1482 if (frames[0] instanceof AlignFrame)
1484 source = ((AlignFrame) frames[0]).getCurrentView();
1486 else if (frames[0] instanceof TreePanel)
1488 source = ((TreePanel) frames[0]).getViewPort();
1490 else if (frames[0] instanceof PCAPanel)
1492 source = ((PCAPanel) frames[0]).av;
1494 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1496 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1501 for (int i = 0; i < frames.length; i++)
1504 if (frames[i] == null)
1508 if (frames[i] instanceof AlignFrame)
1510 target = ((AlignFrame) frames[i]).getCurrentView();
1512 else if (frames[i] instanceof TreePanel)
1514 target = ((TreePanel) frames[i]).getViewPort();
1516 else if (frames[i] instanceof PCAPanel)
1518 target = ((PCAPanel) frames[i]).av;
1520 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1522 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1525 if (source == target)
1531 frames[i].setClosed(true);
1535 frames[i].setIcon(minimize);
1538 frames[i].toFront();
1542 } catch (java.beans.PropertyVetoException ex)
1557 protected void preferences_actionPerformed(ActionEvent e)
1569 public void saveState_actionPerformed(ActionEvent e)
1571 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1574 chooser.setFileView(new JalviewFileView());
1575 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1577 int value = chooser.showSaveDialog(this);
1579 if (value == JalviewFileChooser.APPROVE_OPTION)
1581 final Desktop me = this;
1582 final java.io.File choice = chooser.getSelectedFile();
1583 setProjectFile(choice);
1585 new Thread(new Runnable()
1590 // TODO: refactor to Jalview desktop session controller action.
1591 setProgressBar(MessageManager.formatMessage(
1592 "label.saving_jalview_project",
1593 new Object[] { choice.getName() }), choice.hashCode());
1594 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1595 choice.getParent());
1596 // TODO catch and handle errors for savestate
1597 // TODO prevent user from messing with the Desktop whilst we're saving
1600 new Jalview2XML().saveState(choice);
1601 } catch (OutOfMemoryError oom)
1603 new OOMWarning("Whilst saving current state to "
1604 + choice.getName(), oom);
1605 } catch (Exception ex)
1608 "Problems whilst trying to save to " + choice.getName(),
1610 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1611 "label.error_whilst_saving_current_state_to",
1612 new Object[] { choice.getName() }), MessageManager
1613 .getString("label.couldnt_save_project"),
1614 JvOptionPane.WARNING_MESSAGE);
1616 setProgressBar(null, choice.hashCode());
1622 private void setProjectFile(File choice)
1624 this.projectFile = choice;
1627 public File getProjectFile()
1629 return this.projectFile;
1639 public void loadState_actionPerformed(ActionEvent e)
1641 JalviewFileChooser chooser = new JalviewFileChooser(
1642 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1643 "jvp", "jar" }, new String[] { "Jalview Project",
1644 "Jalview Project (old)" }, "Jalview Project");
1645 chooser.setFileView(new JalviewFileView());
1646 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1648 int value = chooser.showOpenDialog(this);
1650 if (value == JalviewFileChooser.APPROVE_OPTION)
1652 final File selectedFile = chooser.getSelectedFile();
1653 setProjectFile(selectedFile);
1654 final String choice = selectedFile.getAbsolutePath();
1655 Cache.setProperty("LAST_DIRECTORY",
1656 selectedFile.getParent());
1657 new Thread(new Runnable()
1663 MessageManager.formatMessage(
1664 "label.loading_jalview_project",
1665 new Object[] { choice }), choice.hashCode());
1668 new Jalview2XML().loadJalviewAlign(choice);
1669 } catch (OutOfMemoryError oom)
1671 new OOMWarning("Whilst loading project from " + choice, oom);
1672 } catch (Exception ex)
1674 Cache.log.error("Problems whilst loading project from "
1676 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1678 "label.error_whilst_loading_project_from",
1679 new Object[] { choice }), MessageManager
1680 .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<JPanel>();
1699 public void startLoading(final String fileName)
1701 if (fileLoadingCount == 0)
1703 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1704 "label.loading_file", new Object[] { fileName })));
1709 private JPanel addProgressPanel(String string)
1711 if (progressPanel == null)
1713 progressPanel = new JPanel(new GridLayout(1, 1));
1714 totalProgressCount = 0;
1715 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1717 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1718 JProgressBar progressBar = new JProgressBar();
1719 progressBar.setIndeterminate(true);
1721 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1723 thisprogress.add(progressBar, BorderLayout.CENTER);
1724 progressPanel.add(thisprogress);
1725 ((GridLayout) progressPanel.getLayout())
1726 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1727 ++totalProgressCount;
1728 instance.validate();
1729 return thisprogress;
1732 int totalProgressCount = 0;
1734 private void removeProgressPanel(JPanel progbar)
1736 if (progressPanel != null)
1738 synchronized (progressPanel)
1740 progressPanel.remove(progbar);
1741 GridLayout gl = (GridLayout) progressPanel.getLayout();
1742 gl.setRows(gl.getRows() - 1);
1743 if (--totalProgressCount < 1)
1745 this.getContentPane().remove(progressPanel);
1746 progressPanel = null;
1753 public void stopLoading()
1756 if (fileLoadingCount < 1)
1758 while (fileLoadingPanels.size() > 0)
1760 removeProgressPanel(fileLoadingPanels.remove(0));
1762 fileLoadingPanels.clear();
1763 fileLoadingCount = 0;
1768 public static int getViewCount(String alignmentId)
1770 AlignmentViewport[] aps = getViewports(alignmentId);
1771 return (aps == null) ? 0 : aps.length;
1776 * @param alignmentId
1777 * - if null, all sets are returned
1778 * @return all AlignmentPanels concerning the alignmentId sequence set
1780 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1782 if (Desktop.desktop == null)
1784 // no frames created and in headless mode
1785 // TODO: verify that frames are recoverable when in headless mode
1788 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1789 AlignFrame[] frames = getAlignFrames();
1794 for (AlignFrame af : frames)
1796 for (AlignmentPanel ap : af.alignPanels)
1798 if (alignmentId == null
1799 || alignmentId.equals(ap.av.getSequenceSetId()))
1805 if (aps.size() == 0)
1809 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1814 * get all the viewports on an alignment.
1816 * @param sequenceSetId
1817 * unique alignment id (may be null - all viewports returned in that
1819 * @return all viewports on the alignment bound to sequenceSetId
1821 public static AlignmentViewport[] getViewports(String sequenceSetId)
1823 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1824 if (desktop != null)
1826 AlignFrame[] frames = Desktop.getAlignFrames();
1828 for (AlignFrame afr : frames)
1830 if (sequenceSetId == null
1831 || 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(MessageManager
1955 .getString("label.open_saved_vamsas_session"));
1956 chooser.setToolTipText(MessageManager
1957 .getString("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()))
1967 .showInternalMessageDialog(
1969 MessageManager.formatMessage(
1970 "label.couldnt_import_as_vamsas_session",
1971 new Object[] { fle }),
1973 .getString("label.vamsas_document_import_failed"),
1974 JvOptionPane.ERROR_MESSAGE);
1980 jalview.bin.Cache.log
1981 .error("Implementation error - load session from a running session is not supported.");
1986 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1989 * @return true if import was a success and a session was started.
1991 public boolean vamsasImport(URL url)
1993 // TODO: create progress bar
1994 if (v_client != null)
1997 jalview.bin.Cache.log
1998 .error("Implementation error - load session from a running session is not supported.");
2004 // copy the URL content to a temporary local file
2005 // TODO: be a bit cleverer here with nio (?!)
2006 File file = File.createTempFile("vdocfromurl", ".vdj");
2007 FileOutputStream fos = new FileOutputStream(file);
2008 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2009 byte[] buffer = new byte[2048];
2011 while ((ln = bis.read(buffer)) > -1)
2013 fos.write(buffer, 0, ln);
2017 v_client = new jalview.gui.VamsasApplication(this, file,
2018 url.toExternalForm());
2019 } catch (Exception ex)
2021 jalview.bin.Cache.log.error(
2022 "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
2043 .error("Implementation error - load session from a running session is not supported.");
2047 setProgressBar(MessageManager.formatMessage(
2048 "status.importing_vamsas_session_from",
2049 new Object[] { 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",
2057 new Object[] { 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",
2066 new Object[] { file.getName() }), file.hashCode());
2067 return v_client.inSession();
2070 public boolean joinVamsasSession(String mysesid)
2072 if (v_client != null)
2076 .getString("error.try_join_vamsas_session_another"));
2078 if (mysesid == null)
2081 MessageManager.getString("error.invalid_vamsas_session_id"));
2083 v_client = new VamsasApplication(this, mysesid);
2084 setupVamsasConnectedGui();
2085 v_client.initial_update();
2086 return (v_client.inSession());
2090 public void vamsasStart_actionPerformed(ActionEvent e)
2092 if (v_client == null)
2095 // we just start a default session for moment.
2097 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2098 * getProperty("LAST_DIRECTORY"));
2100 * chooser.setFileView(new JalviewFileView());
2101 * chooser.setDialogTitle("Load Vamsas file");
2102 * chooser.setToolTipText("Import");
2104 * int value = chooser.showOpenDialog(this);
2106 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2107 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2109 v_client = new VamsasApplication(this);
2110 setupVamsasConnectedGui();
2111 v_client.initial_update(); // TODO: thread ?
2115 // store current data in session.
2116 v_client.push_update(); // TODO: thread
2120 protected void setupVamsasConnectedGui()
2122 vamsasStart.setText(MessageManager.getString("label.session_update"));
2123 vamsasSave.setVisible(true);
2124 vamsasStop.setVisible(true);
2125 vamsasImport.setVisible(false); // Document import to existing session is
2126 // not possible for vamsas-client-1.0.
2129 protected void setupVamsasDisconnectedGui()
2131 vamsasSave.setVisible(false);
2132 vamsasStop.setVisible(false);
2133 vamsasImport.setVisible(true);
2134 vamsasStart.setText(MessageManager
2135 .getString("label.new_vamsas_session"));
2139 public void vamsasStop_actionPerformed(ActionEvent e)
2141 if (v_client != null)
2143 v_client.end_session();
2145 setupVamsasDisconnectedGui();
2149 protected void buildVamsasStMenu()
2151 if (v_client == null)
2153 String[] sess = null;
2156 sess = VamsasApplication.getSessionList();
2157 } catch (Exception e)
2159 jalview.bin.Cache.log.warn(
2160 "Problem getting current sessions list.", e);
2165 jalview.bin.Cache.log.debug("Got current sessions list: "
2166 + sess.length + " entries.");
2167 VamsasStMenu.removeAll();
2168 for (int i = 0; i < sess.length; i++)
2170 JMenuItem sessit = new JMenuItem();
2171 sessit.setText(sess[i]);
2172 sessit.setToolTipText(MessageManager.formatMessage(
2173 "label.connect_to_session", new Object[] { sess[i] }));
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.formatMessage(
2239 "label.saving_vamsas_doc",
2240 new Object[] { 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.error("Error Whilst saving document to "
2254 } catch (Exception ex)
2256 warnttl = "Problem saving Vamsas Document.";
2257 warnmsg = ex.toString();
2258 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
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(MessageManager
2293 .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<JLabel>();
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 : link.substring(0,
2347 barPos) + ": " + link.substring(barPos + 1);
2348 urls.add(new JLabel(urlMsg));
2356 // ask user to check in case URL links use old style tokens
2357 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2358 JPanel msgPanel = new JPanel();
2359 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2360 msgPanel.add(Box.createVerticalGlue());
2361 JLabel msg = new JLabel(
2363 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2364 JLabel msg2 = new JLabel(
2366 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2368 for (JLabel url : urls)
2374 final JCheckBox jcb = new JCheckBox(
2375 MessageManager.getString("label.do_not_display_again"));
2376 jcb.addActionListener(new ActionListener()
2379 public void actionPerformed(ActionEvent e)
2381 // update Cache settings for "don't show this again"
2382 boolean showWarningAgain = !jcb.isSelected();
2383 Cache.setProperty("CHECKURLLINKS",
2384 Boolean.valueOf(showWarningAgain).toString());
2389 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2391 .getString("label.SEQUENCE_ID_no_longer_used"),
2392 JvOptionPane.WARNING_MESSAGE);
2399 * Proxy class for JDesktopPane which optionally displays the current memory
2400 * usage and highlights the desktop area with a red bar if free memory runs
2405 public class MyDesktopPane extends JDesktopPane implements Runnable
2408 private static final float ONE_MB = 1048576f;
2410 boolean showMemoryUsage = false;
2414 java.text.NumberFormat df;
2416 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2419 public MyDesktopPane(boolean showMemoryUsage)
2421 showMemoryUsage(showMemoryUsage);
2424 public void showMemoryUsage(boolean showMemory)
2426 this.showMemoryUsage = showMemory;
2429 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(
2486 "label.memory_stats",
2487 new Object[] { df.format(totalFreeMemory),
2488 df.format(maxMemory), df.format(percentUsage) }), 10,
2489 getHeight() - fm.getHeight());
2496 * fixes stacking order after a modal dialog to ensure windows that should be
2497 * on top actually are
2499 public void relayerWindows()
2505 * Accessor method to quickly get all the AlignmentFrames loaded.
2507 * @return an array of AlignFrame, or null if none found
2509 public static AlignFrame[] getAlignFrames()
2511 if (Jalview.isHeadlessMode())
2513 // Desktop.desktop is null in headless mode
2514 return new AlignFrame[] { Jalview.currentAlignFrame };
2517 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2523 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2525 for (int i = frames.length - 1; i > -1; i--)
2527 if (frames[i] instanceof AlignFrame)
2529 avp.add((AlignFrame) frames[i]);
2531 else if (frames[i] instanceof SplitFrame)
2534 * Also check for a split frame containing an AlignFrame
2536 GSplitFrame sf = (GSplitFrame) frames[i];
2537 if (sf.getTopFrame() instanceof AlignFrame)
2539 avp.add((AlignFrame) sf.getTopFrame());
2541 if (sf.getBottomFrame() instanceof AlignFrame)
2543 avp.add((AlignFrame) sf.getBottomFrame());
2547 if (avp.size() == 0)
2551 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2556 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2560 public GStructureViewer[] getJmols()
2562 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2568 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2570 for (int i = frames.length - 1; i > -1; i--)
2572 if (frames[i] instanceof AppJmol)
2574 GStructureViewer af = (GStructureViewer) frames[i];
2578 if (avp.size() == 0)
2582 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2587 * Add Groovy Support to Jalview
2590 public void groovyShell_actionPerformed()
2594 openGroovyConsole();
2595 } catch (Exception ex)
2597 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2598 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2600 MessageManager.getString("label.couldnt_create_groovy_shell"),
2601 MessageManager.getString("label.groovy_support_failed"),
2602 JvOptionPane.ERROR_MESSAGE);
2607 * Open the Groovy console
2609 void openGroovyConsole()
2611 if (groovyConsole == null)
2613 groovyConsole = new groovy.ui.Console();
2614 groovyConsole.setVariable("Jalview", this);
2615 groovyConsole.run();
2618 * We allow only one console at a time, so that AlignFrame menu option
2619 * 'Calculate | Run Groovy script' is unambiguous.
2620 * Disable 'Groovy Console', and enable 'Run script', when the console is
2621 * opened, and the reverse when it is closed
2623 Window window = (Window) groovyConsole.getFrame();
2624 window.addWindowListener(new WindowAdapter()
2627 public void windowClosed(WindowEvent e)
2630 * rebind CMD-Q from Groovy Console to Jalview Quit
2633 enableExecuteGroovy(false);
2639 * show Groovy console window (after close and reopen)
2641 ((Window) groovyConsole.getFrame()).setVisible(true);
2644 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2645 * and disable opening a second console
2647 enableExecuteGroovy(true);
2651 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2652 * binding when opened
2654 protected void addQuitHandler()
2656 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2657 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2658 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2659 getRootPane().getActionMap().put("Quit", new AbstractAction()
2662 public void actionPerformed(ActionEvent e)
2670 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2673 * true if Groovy console is open
2675 public void enableExecuteGroovy(boolean enabled)
2678 * disable opening a second Groovy console
2679 * (or re-enable when the console is closed)
2681 groovyShell.setEnabled(!enabled);
2683 AlignFrame[] alignFrames = getAlignFrames();
2684 if (alignFrames != null)
2686 for (AlignFrame af : alignFrames)
2688 af.setGroovyEnabled(enabled);
2694 * Progress bars managed by the IProgressIndicator method.
2696 private Hashtable<Long, JPanel> progressBars;
2698 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2703 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2706 public void setProgressBar(String message, long id)
2708 if (progressBars == null)
2710 progressBars = new Hashtable<Long, JPanel>();
2711 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2714 if (progressBars.get(new Long(id)) != null)
2716 JPanel panel = progressBars.remove(new Long(id));
2717 if (progressBarHandlers.contains(new Long(id)))
2719 progressBarHandlers.remove(new Long(id));
2721 removeProgressPanel(panel);
2725 progressBars.put(new Long(id), addProgressPanel(message));
2732 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2733 * jalview.gui.IProgressIndicatorHandler)
2736 public void registerHandler(final long id,
2737 final IProgressIndicatorHandler handler)
2739 if (progressBarHandlers == null
2740 || !progressBars.containsKey(new Long(id)))
2744 .getString("error.call_setprogressbar_before_registering_handler"));
2746 progressBarHandlers.put(new Long(id), handler);
2747 final JPanel progressPanel = progressBars.get(new Long(id));
2748 if (handler.canCancel())
2750 JButton cancel = new JButton(
2751 MessageManager.getString("action.cancel"));
2752 final IProgressIndicator us = this;
2753 cancel.addActionListener(new ActionListener()
2757 public void actionPerformed(ActionEvent e)
2759 handler.cancelActivity(id);
2760 us.setProgressBar(MessageManager.formatMessage(
2761 "label.cancelled_params",
2762 new Object[] { ((JLabel) progressPanel.getComponent(0))
2766 progressPanel.add(cancel, BorderLayout.EAST);
2772 * @return true if any progress bars are still active
2775 public boolean operationInProgress()
2777 if (progressBars != null && progressBars.size() > 0)
2785 * This will return the first AlignFrame holding the given viewport instance.
2786 * It will break if there are more than one AlignFrames viewing a particular
2790 * @return alignFrame for viewport
2792 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2794 if (desktop != null)
2796 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2797 for (int panel = 0; aps != null && panel < aps.length; panel++)
2799 if (aps[panel] != null && aps[panel].av == viewport)
2801 return aps[panel].alignFrame;
2808 public VamsasApplication getVamsasApplication()
2815 * flag set if jalview GUI is being operated programmatically
2817 private boolean inBatchMode = false;
2820 * check if jalview GUI is being operated programmatically
2822 * @return inBatchMode
2824 public boolean isInBatchMode()
2830 * set flag if jalview GUI is being operated programmatically
2832 * @param inBatchMode
2834 public void setInBatchMode(boolean inBatchMode)
2836 this.inBatchMode = inBatchMode;
2839 public void startServiceDiscovery()
2841 startServiceDiscovery(false);
2844 public void startServiceDiscovery(boolean blocking)
2846 boolean alive = true;
2847 Thread t0 = null, t1 = null, t2 = null;
2848 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2851 // todo: changesupport handlers need to be transferred
2852 if (discoverer == null)
2854 discoverer = new jalview.ws.jws1.Discoverer();
2855 // register PCS handler for desktop.
2856 discoverer.addPropertyChangeListener(changeSupport);
2858 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2859 // until we phase out completely
2860 (t0 = new Thread(discoverer)).start();
2863 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2865 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2870 // TODO: do rest service discovery
2879 } catch (Exception e)
2882 alive = (t1 != null && t1.isAlive())
2883 || (t2 != null && t2.isAlive())
2884 || (t3 != null && t3.isAlive())
2885 || (t0 != null && t0.isAlive());
2891 * called to check if the service discovery process completed successfully.
2895 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2897 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2899 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2900 .getErrorMessages();
2903 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2905 if (serviceChangedDialog == null)
2907 // only run if we aren't already displaying one of these.
2908 addDialogThread(serviceChangedDialog = new Runnable()
2915 * JalviewDialog jd =new JalviewDialog() {
2917 * @Override protected void cancelPressed() { // TODO
2918 * Auto-generated method stub
2920 * }@Override protected void okPressed() { // TODO
2921 * Auto-generated method stub
2923 * }@Override protected void raiseClosed() { // TODO
2924 * Auto-generated method stub
2926 * } }; jd.initDialogFrame(new
2927 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2928 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2929 * + " or mis-configured HTTP proxy settings.<br/>" +
2930 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2932 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2933 * ), true, true, "Web Service Configuration Problem", 450,
2936 * jd.waitForInput();
2942 "<html><table width=\"450\"><tr><td>"
2944 + "</td></tr></table>"
2945 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2946 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2947 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2948 + " Tools->Preferences dialog box to change them.</p></html>"),
2949 "Web Service Configuration Problem",
2950 JvOptionPane.DEFAULT_OPTION,
2951 JvOptionPane.ERROR_MESSAGE);
2952 serviceChangedDialog = null;
2961 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2968 private Runnable serviceChangedDialog = null;
2971 * start a thread to open a URL in the configured browser. Pops up a warning
2972 * dialog to the user if there is an exception when calling out to the browser
2977 public static void showUrl(final String url)
2979 showUrl(url, Desktop.instance);
2983 * Like showUrl but allows progress handler to be specified
2987 * (null) or object implementing IProgressIndicator
2989 public static void showUrl(final String url,
2990 final IProgressIndicator progress)
2992 new Thread(new Runnable()
2999 if (progress != null)
3001 progress.setProgressBar(MessageManager.formatMessage(
3002 "status.opening_params", new Object[] { url }), this
3005 jalview.util.BrowserLauncher.openURL(url);
3006 } catch (Exception ex)
3008 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3010 .getString("label.web_browser_not_found_unix"),
3011 MessageManager.getString("label.web_browser_not_found"),
3012 JvOptionPane.WARNING_MESSAGE);
3014 ex.printStackTrace();
3016 if (progress != null)
3018 progress.setProgressBar(null, this.hashCode());
3024 public static WsParamSetManager wsparamManager = null;
3026 public static ParamManager getUserParameterStore()
3028 if (wsparamManager == null)
3030 wsparamManager = new WsParamSetManager();
3032 return wsparamManager;
3036 * static hyperlink handler proxy method for use by Jalview's internal windows
3040 public static void hyperlinkUpdate(HyperlinkEvent e)
3042 if (e.getEventType() == EventType.ACTIVATED)
3047 url = e.getURL().toString();
3048 Desktop.showUrl(url);
3049 } catch (Exception x)
3053 if (Cache.log != null)
3055 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3059 System.err.println("Couldn't handle string " + url
3063 // ignore any exceptions due to dud links.
3070 * single thread that handles display of dialogs to user.
3072 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3075 * flag indicating if dialogExecutor should try to acquire a permit
3077 private volatile boolean dialogPause = true;
3082 private java.util.concurrent.Semaphore block = new Semaphore(0);
3084 private static groovy.ui.Console groovyConsole;
3087 * add another dialog thread to the queue
3091 public void addDialogThread(final Runnable prompter)
3093 dialogExecutor.submit(new Runnable()
3103 } catch (InterruptedException x)
3108 if (instance == null)
3114 SwingUtilities.invokeAndWait(prompter);
3115 } catch (Exception q)
3117 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3123 public void startDialogQueue()
3125 // set the flag so we don't pause waiting for another permit and semaphore
3126 // the current task to begin
3127 dialogPause = false;
3132 protected void snapShotWindow_actionPerformed(ActionEvent e)
3136 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3137 "View of Desktop", getWidth(), getHeight(), of = new File(
3138 "Jalview_snapshot" + System.currentTimeMillis()
3139 + ".eps"), "View of desktop", null, 0, false);
3142 paintAll(im.getGraphics());
3144 } catch (Exception q)
3146 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3150 Cache.log.info("Successfully written snapshot to file "
3151 + of.getAbsolutePath());
3155 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3156 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3157 * and location last time the view was expanded (if any). However it does not
3158 * remember the split pane divider location - this is set to match the
3159 * 'exploding' frame.
3163 public void explodeViews(SplitFrame sf)
3165 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3166 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3167 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3169 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3171 int viewCount = topPanels.size();
3178 * Processing in reverse order works, forwards order leaves the first panels
3179 * not visible. I don't know why!
3181 for (int i = viewCount - 1; i >= 0; i--)
3184 * Make new top and bottom frames. These take over the respective
3185 * AlignmentPanel objects, including their AlignmentViewports, so the
3186 * cdna/protein relationships between the viewports is carried over to the
3189 * explodedGeometry holds the (x, y) position of the previously exploded
3190 * SplitFrame, and the (width, height) of the AlignFrame component
3192 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3193 AlignFrame newTopFrame = new AlignFrame(topPanel);
3194 newTopFrame.setSize(oldTopFrame.getSize());
3195 newTopFrame.setVisible(true);
3196 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3197 .getExplodedGeometry();
3198 if (geometry != null)
3200 newTopFrame.setSize(geometry.getSize());
3203 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3204 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3205 newBottomFrame.setSize(oldBottomFrame.getSize());
3206 newBottomFrame.setVisible(true);
3207 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3208 .getExplodedGeometry();
3209 if (geometry != null)
3211 newBottomFrame.setSize(geometry.getSize());
3214 topPanel.av.setGatherViewsHere(false);
3215 bottomPanel.av.setGatherViewsHere(false);
3216 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3218 if (geometry != null)
3220 splitFrame.setLocation(geometry.getLocation());
3222 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3226 * Clear references to the panels (now relocated in the new SplitFrames)
3227 * before closing the old SplitFrame.
3230 bottomPanels.clear();
3235 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3236 * back into the given SplitFrame as additional views. Note that the gathered
3237 * frames may themselves have multiple views.
3241 public void gatherViews(GSplitFrame source)
3244 * special handling of explodedGeometry for a view within a SplitFrame: - it
3245 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3246 * height) of the AlignFrame component
3248 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3249 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3250 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3251 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3252 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3253 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3255 myTopFrame.viewport.setGatherViewsHere(true);
3256 myBottomFrame.viewport.setGatherViewsHere(true);
3257 String topViewId = myTopFrame.viewport.getSequenceSetId();
3258 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3260 JInternalFrame[] frames = desktop.getAllFrames();
3261 for (JInternalFrame frame : frames)
3263 if (frame instanceof SplitFrame && frame != source)
3265 SplitFrame sf = (SplitFrame) frame;
3266 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3267 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3268 boolean gatherThis = false;
3269 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3271 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3272 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3273 if (topViewId.equals(topPanel.av.getSequenceSetId())
3274 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3277 topPanel.av.setGatherViewsHere(false);
3278 bottomPanel.av.setGatherViewsHere(false);
3279 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3280 topFrame.getSize()));
3281 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3282 .getLocation(), bottomFrame.getSize()));
3283 myTopFrame.addAlignmentPanel(topPanel, false);
3284 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3290 topFrame.getAlignPanels().clear();
3291 bottomFrame.getAlignPanels().clear();
3298 * The dust settles...give focus to the tab we did this from.
3300 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3303 public static groovy.ui.Console getGroovyConsole()
3305 return groovyConsole;
3308 public static void transferFromDropTarget(List<String> files,
3309 List<DataSourceType> protocols, DropTargetDropEvent evt,
3314 DataFlavor uriListFlavor = new DataFlavor(
3315 "text/uri-list;class=java.lang.String");
3316 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3318 // Works on Windows and MacOSX
3319 Cache.log.debug("Drop handled as javaFileListFlavor");
3320 for (Object file : (List) t
3321 .getTransferData(DataFlavor.javaFileListFlavor))
3323 files.add(((File) file).toString());
3324 protocols.add(DataSourceType.FILE);
3329 // Unix like behaviour
3330 boolean added = false;
3332 if (t.isDataFlavorSupported(uriListFlavor))
3334 Cache.log.debug("Drop handled as uriListFlavor");
3335 // This is used by Unix drag system
3336 data = (String) t.getTransferData(uriListFlavor);
3340 // fallback to text: workaround - on OSX where there's a JVM bug
3341 Cache.log.debug("standard URIListFlavor failed. Trying text");
3342 // try text fallback
3343 data = (String) t.getTransferData(new DataFlavor(
3344 "text/plain;class=java.lang.String"));
3345 if (Cache.log.isDebugEnabled())
3347 Cache.log.debug("fallback returned " + data);
3350 while (protocols.size() < files.size())
3352 Cache.log.debug("Adding missing FILE protocol for "
3353 + files.get(protocols.size()));
3354 protocols.add(DataSourceType.FILE);
3356 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3357 data, "\r\n"); st.hasMoreTokens();)
3360 String s = st.nextToken();
3361 if (s.startsWith("#"))
3363 // the line is a comment (as per the RFC 2483)
3366 java.net.URI uri = new java.net.URI(s);
3367 if (uri.getScheme().toLowerCase().startsWith("http"))
3369 protocols.add(DataSourceType.URL);
3370 files.add(uri.toString());
3374 // otherwise preserve old behaviour: catch all for file objects
3375 java.io.File file = new java.io.File(uri);
3376 protocols.add(DataSourceType.FILE);
3377 files.add(file.toString());
3380 if (Cache.log.isDebugEnabled())
3382 if (data == null || !added)
3385 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3386 for (DataFlavor fl : t.getTransferDataFlavors())
3388 Cache.log.debug("Supported transfer dataflavor: "
3390 Object df = t.getTransferData(fl);
3393 Cache.log.debug("Retrieves: " + df);
3397 Cache.log.debug("Retrieved nothing");
3406 * Sets the Preferences property for experimental features to True or False
3407 * depending on the state of the controlling menu item
3410 protected void showExperimental_actionPerformed(boolean selected)
3412 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));