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())));
366 Rectangle dims = getLastKnownDimensions("");
373 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
374 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
377 jconsole = new Console(this, showjconsole);
378 // add essential build information
380 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
381 + "\n" + "Jalview Installation: "
382 + jalview.bin.Cache.getDefault("INSTALLATION",
384 + "\n" + "Build Date: "
385 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
386 + "\n" + "Java version: "
387 + System.getProperty("java.version") + "\n"
388 + System.getProperty("os.arch") + " "
389 + System.getProperty("os.name") + " "
390 + System.getProperty("os.version"));
392 showConsole(showjconsole);
394 showNews.setVisible(false);
396 experimentalFeatures.setSelected(showExperimental());
398 getIdentifiersOrgData();
402 this.addWindowListener(new WindowAdapter()
405 public void windowClosing(WindowEvent evt)
412 this.addMouseListener(ma = new MouseAdapter()
415 public void mousePressed(MouseEvent evt)
417 if (evt.isPopupTrigger()) // Mac
419 showPasteMenu(evt.getX(), evt.getY());
424 public void mouseReleased(MouseEvent evt)
426 if (evt.isPopupTrigger()) // Windows
428 showPasteMenu(evt.getX(), evt.getY());
432 desktop.addMouseListener(ma);
434 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
435 // Spawn a thread that shows the splashscreen
436 SwingUtilities.invokeLater(new Runnable()
445 // Thread off a new instance of the file chooser - this reduces the time it
446 // takes to open it later on.
447 new Thread(new Runnable()
452 Cache.log.debug("Filechooser init thread started.");
453 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
454 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
456 Cache.log.debug("Filechooser init thread finished.");
459 // Add the service change listener
460 changeSupport.addJalviewPropertyChangeListener("services",
461 new PropertyChangeListener()
465 public void propertyChange(PropertyChangeEvent evt)
467 Cache.log.debug("Firing service changed event for "
468 + evt.getNewValue());
469 JalviewServicesChanged(evt);
476 * Answers true if user preferences to enable experimental features is True
481 public boolean showExperimental()
483 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
484 Boolean.FALSE.toString());
485 return Boolean.valueOf(experimental).booleanValue();
488 public void doConfigureStructurePrefs()
490 // configure services
491 StructureSelectionManager ssm = StructureSelectionManager
492 .getStructureSelectionManager(this);
493 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
495 ssm.setAddTempFacAnnot(jalview.bin.Cache
496 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
497 ssm.setProcessSecondaryStructure(jalview.bin.Cache
498 .getDefault(Preferences.STRUCT_FROM_PDB, true));
499 ssm.setSecStructServices(
500 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
504 ssm.setAddTempFacAnnot(false);
505 ssm.setProcessSecondaryStructure(false);
506 ssm.setSecStructServices(false);
510 public void checkForNews()
512 final Desktop me = this;
513 // Thread off the news reader, in case there are connection problems.
514 addDialogThread(new Runnable()
519 Cache.log.debug("Starting news thread.");
521 jvnews = new BlogReader(me);
522 showNews.setVisible(true);
523 Cache.log.debug("Completed news thread.");
528 public void getIdentifiersOrgData()
530 // Thread off the identifiers fetcher
531 addDialogThread(new Runnable()
536 Cache.log.debug("Downloading data from identifiers.org");
537 UrlDownloadClient client = new UrlDownloadClient();
540 client.download(IdOrgSettings.getUrl(),
541 IdOrgSettings.getDownloadLocation());
542 } catch (IOException e)
544 Cache.log.debug("Exception downloading identifiers.org data"
552 protected void showNews_actionPerformed(ActionEvent e)
554 showNews(showNews.isSelected());
557 void showNews(boolean visible)
560 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
561 showNews.setSelected(visible);
562 if (visible && !jvnews.isVisible())
564 new Thread(new Runnable()
569 long now = System.currentTimeMillis();
570 Desktop.instance.setProgressBar(
571 MessageManager.getString("status.refreshing_news"),
573 jvnews.refreshNews();
574 Desktop.instance.setProgressBar(null, now);
583 * recover the last known dimensions for a jalview window
586 * - empty string is desktop, all other windows have unique prefix
587 * @return null or last known dimensions scaled to current geometry (if last
588 * window geom was known)
590 Rectangle getLastKnownDimensions(String windowName)
592 // TODO: lock aspect ratio for scaling desktop Bug #0058199
593 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
594 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
595 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
596 String width = jalview.bin.Cache
597 .getProperty(windowName + "SCREEN_WIDTH");
598 String height = jalview.bin.Cache
599 .getProperty(windowName + "SCREEN_HEIGHT");
600 if ((x != null) && (y != null) && (width != null) && (height != null))
602 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
603 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
604 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
606 // attempt #1 - try to cope with change in screen geometry - this
607 // version doesn't preserve original jv aspect ratio.
608 // take ratio of current screen size vs original screen size.
609 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
610 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
611 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
612 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
613 // rescale the bounds depending upon the current screen geometry.
614 ix = (int) (ix * sw);
615 iw = (int) (iw * sw);
616 iy = (int) (iy * sh);
617 ih = (int) (ih * sh);
618 while (ix >= screenSize.width)
620 jalview.bin.Cache.log.debug(
621 "Window geometry location recall error: shifting horizontal to within screenbounds.");
622 ix -= screenSize.width;
624 while (iy >= screenSize.height)
626 jalview.bin.Cache.log.debug(
627 "Window geometry location recall error: shifting vertical to within screenbounds.");
628 iy -= screenSize.height;
630 jalview.bin.Cache.log.debug(
631 "Got last known dimensions for " + windowName + ": x:" + ix
632 + " y:" + iy + " width:" + iw + " height:" + ih);
634 // return dimensions for new instance
635 return new Rectangle(ix, iy, iw, ih);
640 private void doVamsasClientCheck()
642 if (jalview.bin.Cache.vamsasJarsPresent())
644 setupVamsasDisconnectedGui();
645 VamsasMenu.setVisible(true);
646 final Desktop us = this;
647 VamsasMenu.addMenuListener(new MenuListener()
649 // this listener remembers when the menu was first selected, and
650 // doesn't rebuild the session list until it has been cleared and
652 boolean refresh = true;
655 public void menuCanceled(MenuEvent e)
661 public void menuDeselected(MenuEvent e)
667 public void menuSelected(MenuEvent e)
671 us.buildVamsasStMenu();
676 vamsasStart.setVisible(true);
680 void showPasteMenu(int x, int y)
682 JPopupMenu popup = new JPopupMenu();
683 JMenuItem item = new JMenuItem(
684 MessageManager.getString("label.paste_new_window"));
685 item.addActionListener(new ActionListener()
688 public void actionPerformed(ActionEvent evt)
695 popup.show(this, x, y);
702 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
703 Transferable contents = c.getContents(this);
705 if (contents != null)
707 String file = (String) contents
708 .getTransferData(DataFlavor.stringFlavor);
710 FileFormatI format = new IdentifyFile().identify(file,
711 DataSourceType.PASTE);
713 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
716 } catch (Exception ex)
719 "Unable to paste alignment from system clipboard:\n" + ex);
724 * Adds and opens the given frame to the desktop
735 public static synchronized void addInternalFrame(
736 final JInternalFrame frame, String title, int w, int h)
738 addInternalFrame(frame, title, true, w, h, true, false);
742 * Add an internal frame to the Jalview desktop
749 * When true, display frame immediately, otherwise, caller must call
750 * setVisible themselves.
756 public static synchronized void addInternalFrame(
757 final JInternalFrame frame, String title, boolean makeVisible,
760 addInternalFrame(frame, title, makeVisible, w, h, true, false);
764 * Add an internal frame to the Jalview desktop and make it visible
777 public static synchronized void addInternalFrame(
778 final JInternalFrame frame, String title, int w, int h,
781 addInternalFrame(frame, title, true, w, h, resizable, false);
785 * Add an internal frame to the Jalview desktop
792 * When true, display frame immediately, otherwise, caller must call
793 * setVisible themselves.
800 * @param ignoreMinSize
801 * Do not set the default minimum size for frame
803 public static synchronized void addInternalFrame(
804 final JInternalFrame frame, String title, boolean makeVisible,
805 int w, int h, boolean resizable, boolean ignoreMinSize)
808 // TODO: allow callers to determine X and Y position of frame (eg. via
810 // TODO: consider fixing method to update entries in the window submenu with
811 // the current window title
813 frame.setTitle(title);
814 if (frame.getWidth() < 1 || frame.getHeight() < 1)
818 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
819 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
820 // IF JALVIEW IS RUNNING HEADLESS
821 // ///////////////////////////////////////////////
822 if (instance == null || (System.getProperty("java.awt.headless") != null
823 && System.getProperty("java.awt.headless").equals("true")))
832 frame.setMinimumSize(
833 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
835 // Set default dimension for Alignment Frame window.
836 // The Alignment Frame window could be added from a number of places,
838 // I did this here in order not to miss out on any Alignment frame.
839 if (frame instanceof AlignFrame)
841 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
842 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
846 frame.setVisible(makeVisible);
847 frame.setClosable(true);
848 frame.setResizable(resizable);
849 frame.setMaximizable(resizable);
850 frame.setIconifiable(resizable);
852 if (frame.getX() < 1 && frame.getY() < 1)
854 frame.setLocation(xOffset * openFrameCount,
855 yOffset * ((openFrameCount - 1) % 10) + yOffset);
859 * add an entry for the new frame in the Window menu
860 * (and remove it when the frame is closed)
862 final JMenuItem menuItem = new JMenuItem(title);
863 frame.addInternalFrameListener(new InternalFrameAdapter()
866 public void internalFrameActivated(InternalFrameEvent evt)
868 JInternalFrame itf = desktop.getSelectedFrame();
876 public void internalFrameClosed(InternalFrameEvent evt)
878 PaintRefresher.RemoveComponent(frame);
881 * defensive check to prevent frames being
882 * added half off the window
884 if (openFrameCount > 0)
890 * ensure no reference to alignFrame retained by menu item listener
892 if (menuItem.getActionListeners().length > 0)
894 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
896 windowMenu.remove(menuItem);
897 JInternalFrame itf = desktop.getSelectedFrame();
901 if (itf instanceof AlignFrame)
903 Jalview.setCurrentAlignFrame((AlignFrame) itf);
910 menuItem.addActionListener(new ActionListener()
913 public void actionPerformed(ActionEvent e)
917 frame.setSelected(true);
918 frame.setIcon(false);
919 } catch (java.beans.PropertyVetoException ex)
928 windowMenu.add(menuItem);
933 frame.setSelected(true);
934 frame.requestFocus();
935 } catch (java.beans.PropertyVetoException ve)
937 } catch (java.lang.ClassCastException cex)
940 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
946 public void lostOwnership(Clipboard clipboard, Transferable contents)
950 Desktop.jalviewClipboard = null;
953 internalCopy = false;
957 public void dragEnter(DropTargetDragEvent evt)
962 public void dragExit(DropTargetEvent evt)
967 public void dragOver(DropTargetDragEvent evt)
972 public void dropActionChanged(DropTargetDragEvent evt)
983 public void drop(DropTargetDropEvent evt)
985 boolean success = true;
986 // JAL-1552 - acceptDrop required before getTransferable call for
987 // Java's Transferable for native dnd
988 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
989 Transferable t = evt.getTransferable();
990 List<String> files = new ArrayList<>();
991 List<DataSourceType> protocols = new ArrayList<>();
995 Desktop.transferFromDropTarget(files, protocols, evt, t);
996 } catch (Exception e)
1006 for (int i = 0; i < files.size(); i++)
1008 String file = files.get(i).toString();
1009 DataSourceType protocol = (protocols == null)
1010 ? DataSourceType.FILE
1012 FileFormatI format = null;
1014 if (file.endsWith(".jar"))
1016 format = FileFormat.Jalview;
1021 format = new IdentifyFile().identify(file, protocol);
1024 new FileLoader().LoadFile(file, protocol, format);
1027 } catch (Exception ex)
1032 evt.dropComplete(success); // need this to ensure input focus is properly
1033 // transfered to any new windows created
1043 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1045 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1046 JalviewFileChooser chooser = JalviewFileChooser
1047 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1049 chooser.setFileView(new JalviewFileView());
1050 chooser.setDialogTitle(
1051 MessageManager.getString("label.open_local_file"));
1052 chooser.setToolTipText(MessageManager.getString("action.open"));
1054 int value = chooser.showOpenDialog(this);
1056 if (value == JalviewFileChooser.APPROVE_OPTION)
1058 String choice = chooser.getSelectedFile().getPath();
1059 Cache.setProperty("LAST_DIRECTORY",
1060 chooser.getSelectedFile().getParent());
1062 FileFormatI format = chooser.getSelectedFormat();
1065 * Call IdentifyFile to verify the file contains what its extension implies.
1066 * Skip this step for dynamically added file formats, because
1067 * IdentifyFile does not know how to recognise them.
1069 if (FileFormats.getInstance().isIdentifiable(format))
1073 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1074 } catch (FileFormatException e)
1076 // format = null; //??
1080 if (viewport != null)
1082 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1087 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1099 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1101 // This construct allows us to have a wider textfield
1103 JLabel label = new JLabel(
1104 MessageManager.getString("label.input_file_url"));
1105 final JComboBox history = new JComboBox();
1107 JPanel panel = new JPanel(new GridLayout(2, 1));
1110 history.setPreferredSize(new Dimension(400, 20));
1111 history.setEditable(true);
1112 history.addItem("http://www.");
1114 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1118 if (historyItems != null)
1120 st = new StringTokenizer(historyItems, "\t");
1122 while (st.hasMoreTokens())
1124 history.addItem(st.nextElement());
1128 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1129 MessageManager.getString("label.input_alignment_from_url"),
1130 JvOptionPane.OK_CANCEL_OPTION);
1132 if (reply != JvOptionPane.OK_OPTION)
1137 String url = history.getSelectedItem().toString();
1139 if (url.toLowerCase().endsWith(".jar"))
1141 if (viewport != null)
1143 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1144 FileFormat.Jalview);
1148 new FileLoader().LoadFile(url, DataSourceType.URL,
1149 FileFormat.Jalview);
1154 FileFormatI format = null;
1157 format = new IdentifyFile().identify(url, DataSourceType.URL);
1158 } catch (FileFormatException e)
1160 // TODO revise error handling, distinguish between
1161 // URL not found and response not valid
1166 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1167 MessageManager.formatMessage("label.couldnt_locate",
1170 MessageManager.getString("label.url_not_found"),
1171 JvOptionPane.WARNING_MESSAGE);
1176 if (viewport != null)
1178 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1183 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1189 * Opens the CutAndPaste window for the user to paste an alignment in to
1192 * - if not null, the pasted alignment is added to the current
1193 * alignment; if null, to a new alignment window
1196 public void inputTextboxMenuItem_actionPerformed(
1197 AlignmentViewPanel viewPanel)
1199 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1200 cap.setForInput(viewPanel);
1201 Desktop.addInternalFrame(cap,
1202 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1212 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1213 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1215 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1216 screen.height + "");
1217 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1218 getWidth(), getHeight()));
1220 if (jconsole != null)
1222 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1223 jconsole.stopConsole();
1227 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1230 if (dialogExecutor != null)
1232 dialogExecutor.shutdownNow();
1234 closeAll_actionPerformed(null);
1236 if (groovyConsole != null)
1238 // suppress a possible repeat prompt to save script
1239 groovyConsole.setDirty(false);
1240 groovyConsole.exit();
1245 private void storeLastKnownDimensions(String string, Rectangle jc)
1247 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1248 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1249 + " height:" + jc.height);
1251 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1252 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1253 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1254 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1264 public void aboutMenuItem_actionPerformed(ActionEvent e)
1266 // StringBuffer message = getAboutMessage(false);
1267 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1269 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1270 new Thread(new Runnable()
1275 new SplashScreen(true);
1280 public StringBuffer getAboutMessage(boolean shortv)
1282 StringBuffer message = new StringBuffer();
1283 message.append("<html>");
1286 message.append("<h1><strong>Version: "
1287 + jalview.bin.Cache.getProperty("VERSION")
1288 + "</strong></h1>");
1289 message.append("<strong>Last Updated: <em>"
1290 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1291 + "</em></strong>");
1297 message.append("<strong>Version "
1298 + jalview.bin.Cache.getProperty("VERSION")
1299 + "; last updated: "
1300 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1303 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1304 .equals("Checking"))
1306 message.append("<br>...Checking latest version...</br>");
1308 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1309 .equals(jalview.bin.Cache.getProperty("VERSION")))
1311 boolean red = false;
1312 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1313 .indexOf("automated build") == -1)
1316 // Displayed when code version and jnlp version do not match and code
1317 // version is not a development build
1318 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1321 message.append("<br>!! Version "
1322 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1324 + " is available for download from "
1325 + jalview.bin.Cache.getDefault("www.jalview.org",
1326 "http://www.jalview.org")
1330 message.append("</div>");
1333 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1335 "The Jalview Authors (See AUTHORS file for current list)")
1336 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1337 + "<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"
1338 + "<br><br>If you use Jalview, please cite:"
1339 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1340 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1341 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1353 public void documentationMenuItem_actionPerformed(ActionEvent e)
1357 Help.showHelpWindow();
1358 } catch (Exception ex)
1364 public void closeAll_actionPerformed(ActionEvent e)
1366 // TODO show a progress bar while closing?
1367 JInternalFrame[] frames = desktop.getAllFrames();
1368 for (int i = 0; i < frames.length; i++)
1372 frames[i].setClosed(true);
1373 } catch (java.beans.PropertyVetoException ex)
1377 Jalview.setCurrentAlignFrame(null);
1378 System.out.println("ALL CLOSED");
1379 if (v_client != null)
1381 // TODO clear binding to vamsas document objects on close_all
1385 * reset state of singleton objects as appropriate (clear down session state
1386 * when all windows are closed)
1388 StructureSelectionManager ssm = StructureSelectionManager
1389 .getStructureSelectionManager(this);
1398 public void raiseRelated_actionPerformed(ActionEvent e)
1400 reorderAssociatedWindows(false, false);
1404 public void minimizeAssociated_actionPerformed(ActionEvent e)
1406 reorderAssociatedWindows(true, false);
1409 void closeAssociatedWindows()
1411 reorderAssociatedWindows(false, true);
1417 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1421 protected void garbageCollect_actionPerformed(ActionEvent e)
1423 // We simply collect the garbage
1424 jalview.bin.Cache.log.debug("Collecting garbage...");
1426 jalview.bin.Cache.log.debug("Finished garbage collection.");
1433 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1437 protected void showMemusage_actionPerformed(ActionEvent e)
1439 desktop.showMemoryUsage(showMemusage.isSelected());
1446 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1450 protected void showConsole_actionPerformed(ActionEvent e)
1452 showConsole(showConsole.isSelected());
1455 Console jconsole = null;
1458 * control whether the java console is visible or not
1462 void showConsole(boolean selected)
1464 showConsole.setSelected(selected);
1465 // TODO: decide if we should update properties file
1466 Cache.setProperty("SHOW_JAVA_CONSOLE",
1467 Boolean.valueOf(selected).toString());
1468 jconsole.setVisible(selected);
1471 void reorderAssociatedWindows(boolean minimize, boolean close)
1473 JInternalFrame[] frames = desktop.getAllFrames();
1474 if (frames == null || frames.length < 1)
1479 AlignmentViewport source = null, target = null;
1480 if (frames[0] instanceof AlignFrame)
1482 source = ((AlignFrame) frames[0]).getCurrentView();
1484 else if (frames[0] instanceof TreePanel)
1486 source = ((TreePanel) frames[0]).getViewPort();
1488 else if (frames[0] instanceof PCAPanel)
1490 source = ((PCAPanel) frames[0]).av;
1492 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1494 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1499 for (int i = 0; i < frames.length; i++)
1502 if (frames[i] == null)
1506 if (frames[i] instanceof AlignFrame)
1508 target = ((AlignFrame) frames[i]).getCurrentView();
1510 else if (frames[i] instanceof TreePanel)
1512 target = ((TreePanel) frames[i]).getViewPort();
1514 else if (frames[i] instanceof PCAPanel)
1516 target = ((PCAPanel) frames[i]).av;
1518 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1520 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1523 if (source == target)
1529 frames[i].setClosed(true);
1533 frames[i].setIcon(minimize);
1536 frames[i].toFront();
1540 } catch (java.beans.PropertyVetoException ex)
1555 protected void preferences_actionPerformed(ActionEvent e)
1567 public void saveState_actionPerformed(ActionEvent e)
1569 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1572 chooser.setFileView(new JalviewFileView());
1573 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1575 int value = chooser.showSaveDialog(this);
1577 if (value == JalviewFileChooser.APPROVE_OPTION)
1579 final Desktop me = this;
1580 final java.io.File choice = chooser.getSelectedFile();
1581 setProjectFile(choice);
1583 new Thread(new Runnable()
1588 // TODO: refactor to Jalview desktop session controller action.
1589 setProgressBar(MessageManager.formatMessage(
1590 "label.saving_jalview_project", new Object[]
1591 { choice.getName() }), choice.hashCode());
1592 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1593 choice.getParent());
1594 // TODO catch and handle errors for savestate
1595 // TODO prevent user from messing with the Desktop whilst we're saving
1598 new Jalview2XML().saveState(choice);
1599 } catch (OutOfMemoryError oom)
1602 "Whilst saving current state to " + choice.getName(),
1604 } catch (Exception ex)
1607 "Problems whilst trying to save to " + choice.getName(),
1609 JvOptionPane.showMessageDialog(me,
1610 MessageManager.formatMessage(
1611 "label.error_whilst_saving_current_state_to",
1613 { choice.getName() }),
1614 MessageManager.getString("label.couldnt_save_project"),
1615 JvOptionPane.WARNING_MESSAGE);
1617 setProgressBar(null, choice.hashCode());
1623 private void setProjectFile(File choice)
1625 this.projectFile = choice;
1628 public File getProjectFile()
1630 return this.projectFile;
1640 public void loadState_actionPerformed(ActionEvent e)
1642 JalviewFileChooser chooser = new JalviewFileChooser(
1643 Cache.getProperty("LAST_DIRECTORY"), new String[]
1646 { "Jalview Project", "Jalview Project (old)" },
1648 chooser.setFileView(new JalviewFileView());
1649 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1651 int value = chooser.showOpenDialog(this);
1653 if (value == JalviewFileChooser.APPROVE_OPTION)
1655 final File selectedFile = chooser.getSelectedFile();
1656 setProjectFile(selectedFile);
1657 final String choice = selectedFile.getAbsolutePath();
1658 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1659 new Thread(new Runnable()
1664 setProgressBar(MessageManager.formatMessage(
1665 "label.loading_jalview_project", new Object[]
1666 { choice }), choice.hashCode());
1669 new Jalview2XML().loadJalviewAlign(choice);
1670 } catch (OutOfMemoryError oom)
1672 new OOMWarning("Whilst loading project from " + choice, oom);
1673 } catch (Exception ex)
1676 "Problems whilst loading project from " + choice, ex);
1677 JvOptionPane.showMessageDialog(Desktop.desktop,
1678 MessageManager.formatMessage(
1679 "label.error_whilst_loading_project_from",
1682 MessageManager.getString("label.couldnt_load_project"),
1683 JvOptionPane.WARNING_MESSAGE);
1685 setProgressBar(null, choice.hashCode());
1692 public void inputSequence_actionPerformed(ActionEvent e)
1694 new SequenceFetcher(this);
1697 JPanel progressPanel;
1699 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1701 public void startLoading(final String fileName)
1703 if (fileLoadingCount == 0)
1705 fileLoadingPanels.add(addProgressPanel(MessageManager
1706 .formatMessage("label.loading_file", new Object[]
1712 private JPanel addProgressPanel(String string)
1714 if (progressPanel == null)
1716 progressPanel = new JPanel(new GridLayout(1, 1));
1717 totalProgressCount = 0;
1718 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1720 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1721 JProgressBar progressBar = new JProgressBar();
1722 progressBar.setIndeterminate(true);
1724 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1726 thisprogress.add(progressBar, BorderLayout.CENTER);
1727 progressPanel.add(thisprogress);
1728 ((GridLayout) progressPanel.getLayout()).setRows(
1729 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1730 ++totalProgressCount;
1731 instance.validate();
1732 return thisprogress;
1735 int totalProgressCount = 0;
1737 private void removeProgressPanel(JPanel progbar)
1739 if (progressPanel != null)
1741 synchronized (progressPanel)
1743 progressPanel.remove(progbar);
1744 GridLayout gl = (GridLayout) progressPanel.getLayout();
1745 gl.setRows(gl.getRows() - 1);
1746 if (--totalProgressCount < 1)
1748 this.getContentPane().remove(progressPanel);
1749 progressPanel = null;
1756 public void stopLoading()
1759 if (fileLoadingCount < 1)
1761 while (fileLoadingPanels.size() > 0)
1763 removeProgressPanel(fileLoadingPanels.remove(0));
1765 fileLoadingPanels.clear();
1766 fileLoadingCount = 0;
1771 public static int getViewCount(String alignmentId)
1773 AlignmentViewport[] aps = getViewports(alignmentId);
1774 return (aps == null) ? 0 : aps.length;
1779 * @param alignmentId
1780 * - if null, all sets are returned
1781 * @return all AlignmentPanels concerning the alignmentId sequence set
1783 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1785 if (Desktop.desktop == null)
1787 // no frames created and in headless mode
1788 // TODO: verify that frames are recoverable when in headless mode
1791 List<AlignmentPanel> aps = new ArrayList<>();
1792 AlignFrame[] frames = getAlignFrames();
1797 for (AlignFrame af : frames)
1799 for (AlignmentPanel ap : af.alignPanels)
1801 if (alignmentId == null
1802 || alignmentId.equals(ap.av.getSequenceSetId()))
1808 if (aps.size() == 0)
1812 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1817 * get all the viewports on an alignment.
1819 * @param sequenceSetId
1820 * unique alignment id (may be null - all viewports returned in that
1822 * @return all viewports on the alignment bound to sequenceSetId
1824 public static AlignmentViewport[] getViewports(String sequenceSetId)
1826 List<AlignmentViewport> viewp = new ArrayList<>();
1827 if (desktop != null)
1829 AlignFrame[] frames = Desktop.getAlignFrames();
1831 for (AlignFrame afr : frames)
1833 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1834 .equals(sequenceSetId))
1836 if (afr.alignPanels != null)
1838 for (AlignmentPanel ap : afr.alignPanels)
1840 if (sequenceSetId == null
1841 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1849 viewp.add(afr.getViewport());
1853 if (viewp.size() > 0)
1855 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1862 * Explode the views in the given frame into separate AlignFrame
1866 public static void explodeViews(AlignFrame af)
1868 int size = af.alignPanels.size();
1874 for (int i = 0; i < size; i++)
1876 AlignmentPanel ap = af.alignPanels.get(i);
1877 AlignFrame newaf = new AlignFrame(ap);
1880 * Restore the view's last exploded frame geometry if known. Multiple
1881 * views from one exploded frame share and restore the same (frame)
1882 * position and size.
1884 Rectangle geometry = ap.av.getExplodedGeometry();
1885 if (geometry != null)
1887 newaf.setBounds(geometry);
1890 ap.av.setGatherViewsHere(false);
1892 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1893 AlignFrame.DEFAULT_HEIGHT);
1896 af.alignPanels.clear();
1897 af.closeMenuItem_actionPerformed(true);
1902 * Gather expanded views (separate AlignFrame's) with the same sequence set
1903 * identifier back in to this frame as additional views, and close the
1904 * expanded views. Note the expanded frames may themselves have multiple
1905 * views. We take the lot.
1909 public void gatherViews(AlignFrame source)
1911 source.viewport.setGatherViewsHere(true);
1912 source.viewport.setExplodedGeometry(source.getBounds());
1913 JInternalFrame[] frames = desktop.getAllFrames();
1914 String viewId = source.viewport.getSequenceSetId();
1916 for (int t = 0; t < frames.length; t++)
1918 if (frames[t] instanceof AlignFrame && frames[t] != source)
1920 AlignFrame af = (AlignFrame) frames[t];
1921 boolean gatherThis = false;
1922 for (int a = 0; a < af.alignPanels.size(); a++)
1924 AlignmentPanel ap = af.alignPanels.get(a);
1925 if (viewId.equals(ap.av.getSequenceSetId()))
1928 ap.av.setGatherViewsHere(false);
1929 ap.av.setExplodedGeometry(af.getBounds());
1930 source.addAlignmentPanel(ap, false);
1936 af.alignPanels.clear();
1937 af.closeMenuItem_actionPerformed(true);
1944 jalview.gui.VamsasApplication v_client = null;
1947 public void vamsasImport_actionPerformed(ActionEvent e)
1949 if (v_client == null)
1951 // Load and try to start a session.
1952 JalviewFileChooser chooser = new JalviewFileChooser(
1953 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1955 chooser.setFileView(new JalviewFileView());
1956 chooser.setDialogTitle(
1957 MessageManager.getString("label.open_saved_vamsas_session"));
1958 chooser.setToolTipText(MessageManager.getString(
1959 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1961 int value = chooser.showOpenDialog(this);
1963 if (value == JalviewFileChooser.APPROVE_OPTION)
1965 String fle = chooser.getSelectedFile().toString();
1966 if (!vamsasImport(chooser.getSelectedFile()))
1968 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1969 MessageManager.formatMessage(
1970 "label.couldnt_import_as_vamsas_session",
1974 .getString("label.vamsas_document_import_failed"),
1975 JvOptionPane.ERROR_MESSAGE);
1981 jalview.bin.Cache.log.error(
1982 "Implementation error - load session from a running session is not supported.");
1987 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1990 * @return true if import was a success and a session was started.
1992 public boolean vamsasImport(URL url)
1994 // TODO: create progress bar
1995 if (v_client != null)
1998 jalview.bin.Cache.log.error(
1999 "Implementation error - load session from a running session is not supported.");
2005 // copy the URL content to a temporary local file
2006 // TODO: be a bit cleverer here with nio (?!)
2007 File file = File.createTempFile("vdocfromurl", ".vdj");
2008 FileOutputStream fos = new FileOutputStream(file);
2009 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2010 byte[] buffer = new byte[2048];
2012 while ((ln = bis.read(buffer)) > -1)
2014 fos.write(buffer, 0, ln);
2018 v_client = new jalview.gui.VamsasApplication(this, file,
2019 url.toExternalForm());
2020 } catch (Exception ex)
2022 jalview.bin.Cache.log.error(
2023 "Failed to create new vamsas session from contents of URL "
2028 setupVamsasConnectedGui();
2029 v_client.initial_update(); // TODO: thread ?
2030 return v_client.inSession();
2034 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2037 * @return true if import was a success and a session was started.
2039 public boolean vamsasImport(File file)
2041 if (v_client != null)
2044 jalview.bin.Cache.log.error(
2045 "Implementation error - load session from a running session is not supported.");
2049 setProgressBar(MessageManager.formatMessage(
2050 "status.importing_vamsas_session_from", new Object[]
2051 { file.getName() }), file.hashCode());
2054 v_client = new jalview.gui.VamsasApplication(this, file, null);
2055 } catch (Exception ex)
2057 setProgressBar(MessageManager.formatMessage(
2058 "status.importing_vamsas_session_from", new Object[]
2059 { file.getName() }), file.hashCode());
2060 jalview.bin.Cache.log.error(
2061 "New vamsas session from existing session file failed:", ex);
2064 setupVamsasConnectedGui();
2065 v_client.initial_update(); // TODO: thread ?
2066 setProgressBar(MessageManager.formatMessage(
2067 "status.importing_vamsas_session_from", new Object[]
2068 { file.getName() }), file.hashCode());
2069 return v_client.inSession();
2072 public boolean joinVamsasSession(String mysesid)
2074 if (v_client != null)
2076 throw new Error(MessageManager
2077 .getString("error.try_join_vamsas_session_another"));
2079 if (mysesid == null)
2082 MessageManager.getString("error.invalid_vamsas_session_id"));
2084 v_client = new VamsasApplication(this, mysesid);
2085 setupVamsasConnectedGui();
2086 v_client.initial_update();
2087 return (v_client.inSession());
2091 public void vamsasStart_actionPerformed(ActionEvent e)
2093 if (v_client == null)
2096 // we just start a default session for moment.
2098 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2099 * getProperty("LAST_DIRECTORY"));
2101 * chooser.setFileView(new JalviewFileView());
2102 * chooser.setDialogTitle("Load Vamsas file");
2103 * chooser.setToolTipText("Import");
2105 * int value = chooser.showOpenDialog(this);
2107 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2108 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2110 v_client = new VamsasApplication(this);
2111 setupVamsasConnectedGui();
2112 v_client.initial_update(); // TODO: thread ?
2116 // store current data in session.
2117 v_client.push_update(); // TODO: thread
2121 protected void setupVamsasConnectedGui()
2123 vamsasStart.setText(MessageManager.getString("label.session_update"));
2124 vamsasSave.setVisible(true);
2125 vamsasStop.setVisible(true);
2126 vamsasImport.setVisible(false); // Document import to existing session is
2127 // not possible for vamsas-client-1.0.
2130 protected void setupVamsasDisconnectedGui()
2132 vamsasSave.setVisible(false);
2133 vamsasStop.setVisible(false);
2134 vamsasImport.setVisible(true);
2136 .setText(MessageManager.getString("label.new_vamsas_session"));
2140 public void vamsasStop_actionPerformed(ActionEvent e)
2142 if (v_client != null)
2144 v_client.end_session();
2146 setupVamsasDisconnectedGui();
2150 protected void buildVamsasStMenu()
2152 if (v_client == null)
2154 String[] sess = null;
2157 sess = VamsasApplication.getSessionList();
2158 } catch (Exception e)
2160 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2166 jalview.bin.Cache.log.debug(
2167 "Got current sessions list: " + sess.length + " entries.");
2168 VamsasStMenu.removeAll();
2169 for (int i = 0; i < sess.length; i++)
2171 JMenuItem sessit = new JMenuItem();
2172 sessit.setText(sess[i]);
2173 sessit.setToolTipText(MessageManager
2174 .formatMessage("label.connect_to_session", new Object[]
2176 final Desktop dsktp = this;
2177 final String mysesid = sess[i];
2178 sessit.addActionListener(new ActionListener()
2182 public void actionPerformed(ActionEvent e)
2184 if (dsktp.v_client == null)
2186 Thread rthr = new Thread(new Runnable()
2192 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2193 dsktp.setupVamsasConnectedGui();
2194 dsktp.v_client.initial_update();
2202 VamsasStMenu.add(sessit);
2204 // don't show an empty menu.
2205 VamsasStMenu.setVisible(sess.length > 0);
2210 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2211 VamsasStMenu.removeAll();
2212 VamsasStMenu.setVisible(false);
2217 // Not interested in the content. Just hide ourselves.
2218 VamsasStMenu.setVisible(false);
2223 public void vamsasSave_actionPerformed(ActionEvent e)
2225 if (v_client != null)
2227 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2228 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2231 chooser.setFileView(new JalviewFileView());
2232 chooser.setDialogTitle(MessageManager
2233 .getString("label.save_vamsas_document_archive"));
2235 int value = chooser.showSaveDialog(this);
2237 if (value == JalviewFileChooser.APPROVE_OPTION)
2239 java.io.File choice = chooser.getSelectedFile();
2240 JPanel progpanel = addProgressPanel(MessageManager
2241 .formatMessage("label.saving_vamsas_doc", new Object[]
2242 { choice.getName() }));
2243 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2244 String warnmsg = null;
2245 String warnttl = null;
2248 v_client.vclient.storeDocument(choice);
2251 warnttl = "Serious Problem saving Vamsas Document";
2252 warnmsg = ex.toString();
2253 jalview.bin.Cache.log
2254 .error("Error Whilst saving document to " + choice, ex);
2256 } catch (Exception ex)
2258 warnttl = "Problem saving Vamsas Document.";
2259 warnmsg = ex.toString();
2260 jalview.bin.Cache.log.warn(
2261 "Exception Whilst saving document to " + choice, ex);
2264 removeProgressPanel(progpanel);
2265 if (warnmsg != null)
2267 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2269 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2275 JPanel vamUpdate = null;
2278 * hide vamsas user gui bits when a vamsas document event is being handled.
2281 * true to hide gui, false to reveal gui
2283 public void setVamsasUpdate(boolean b)
2285 Cache.log.debug("Setting gui for Vamsas update "
2286 + (b ? "in progress" : "finished"));
2288 if (vamUpdate != null)
2290 this.removeProgressPanel(vamUpdate);
2294 vamUpdate = this.addProgressPanel(
2295 MessageManager.getString("label.updating_vamsas_session"));
2297 vamsasStart.setVisible(!b);
2298 vamsasStop.setVisible(!b);
2299 vamsasSave.setVisible(!b);
2302 public JInternalFrame[] getAllFrames()
2304 return desktop.getAllFrames();
2308 * Checks the given url to see if it gives a response indicating that the user
2309 * should be informed of a new questionnaire.
2313 public void checkForQuestionnaire(String url)
2315 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2316 // javax.swing.SwingUtilities.invokeLater(jvq);
2317 new Thread(jvq).start();
2320 public void checkURLLinks()
2322 // Thread off the URL link checker
2323 addDialogThread(new Runnable()
2328 if (Cache.getDefault("CHECKURLLINKS", true))
2330 // check what the actual links are - if it's just the default don't
2331 // bother with the warning
2332 List<String> links = Preferences.sequenceUrlLinks
2335 // only need to check links if there is one with a
2336 // SEQUENCE_ID which is not the default EMBL_EBI link
2337 ListIterator<String> li = links.listIterator();
2338 boolean check = false;
2339 List<JLabel> urls = new ArrayList<>();
2340 while (li.hasNext())
2342 String link = li.next();
2343 if (link.contains(SEQUENCE_ID)
2344 && !link.equals(UrlConstants.DEFAULT_STRING))
2347 int barPos = link.indexOf("|");
2348 String urlMsg = barPos == -1 ? link
2349 : link.substring(0, barPos) + ": "
2350 + link.substring(barPos + 1);
2351 urls.add(new JLabel(urlMsg));
2359 // ask user to check in case URL links use old style tokens
2360 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2361 JPanel msgPanel = new JPanel();
2362 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2363 msgPanel.add(Box.createVerticalGlue());
2364 JLabel msg = new JLabel(MessageManager
2365 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2366 JLabel msg2 = new JLabel(MessageManager
2367 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2369 for (JLabel url : urls)
2375 final JCheckBox jcb = new JCheckBox(
2376 MessageManager.getString("label.do_not_display_again"));
2377 jcb.addActionListener(new ActionListener()
2380 public void actionPerformed(ActionEvent e)
2382 // update Cache settings for "don't show this again"
2383 boolean showWarningAgain = !jcb.isSelected();
2384 Cache.setProperty("CHECKURLLINKS",
2385 Boolean.valueOf(showWarningAgain).toString());
2390 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2392 .getString("label.SEQUENCE_ID_no_longer_used"),
2393 JvOptionPane.WARNING_MESSAGE);
2400 * Proxy class for JDesktopPane which optionally displays the current memory
2401 * usage and highlights the desktop area with a red bar if free memory runs
2406 public class MyDesktopPane extends JDesktopPane implements Runnable
2409 private static final float ONE_MB = 1048576f;
2411 boolean showMemoryUsage = false;
2415 java.text.NumberFormat df;
2417 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2420 public MyDesktopPane(boolean showMemoryUsage)
2422 showMemoryUsage(showMemoryUsage);
2425 public void showMemoryUsage(boolean showMemory)
2427 this.showMemoryUsage = showMemory;
2430 Thread worker = new Thread(this);
2436 public boolean isShowMemoryUsage()
2438 return showMemoryUsage;
2444 df = java.text.NumberFormat.getNumberInstance();
2445 df.setMaximumFractionDigits(2);
2446 runtime = Runtime.getRuntime();
2448 while (showMemoryUsage)
2452 maxMemory = runtime.maxMemory() / ONE_MB;
2453 allocatedMemory = runtime.totalMemory() / ONE_MB;
2454 freeMemory = runtime.freeMemory() / ONE_MB;
2455 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2457 percentUsage = (totalFreeMemory / maxMemory) * 100;
2459 // if (percentUsage < 20)
2461 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2463 // instance.set.setBorder(border1);
2466 // sleep after showing usage
2468 } catch (Exception ex)
2470 ex.printStackTrace();
2476 public void paintComponent(Graphics g)
2478 if (showMemoryUsage && g != null && df != null)
2480 if (percentUsage < 20)
2482 g.setColor(Color.red);
2484 FontMetrics fm = g.getFontMetrics();
2487 g.drawString(MessageManager.formatMessage("label.memory_stats",
2489 { df.format(totalFreeMemory), df.format(maxMemory),
2490 df.format(percentUsage) }),
2491 10, getHeight() - fm.getHeight());
2499 * Accessor method to quickly get all the AlignmentFrames loaded.
2501 * @return an array of AlignFrame, or null if none found
2503 public static AlignFrame[] getAlignFrames()
2505 if (Jalview.isHeadlessMode())
2507 // Desktop.desktop is null in headless mode
2508 return new AlignFrame[] { Jalview.currentAlignFrame };
2511 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2517 List<AlignFrame> avp = new ArrayList<>();
2519 for (int i = frames.length - 1; i > -1; i--)
2521 if (frames[i] instanceof AlignFrame)
2523 avp.add((AlignFrame) frames[i]);
2525 else if (frames[i] instanceof SplitFrame)
2528 * Also check for a split frame containing an AlignFrame
2530 GSplitFrame sf = (GSplitFrame) frames[i];
2531 if (sf.getTopFrame() instanceof AlignFrame)
2533 avp.add((AlignFrame) sf.getTopFrame());
2535 if (sf.getBottomFrame() instanceof AlignFrame)
2537 avp.add((AlignFrame) sf.getBottomFrame());
2541 if (avp.size() == 0)
2545 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2550 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2554 public GStructureViewer[] getJmols()
2556 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2562 List<GStructureViewer> avp = new ArrayList<>();
2564 for (int i = frames.length - 1; i > -1; i--)
2566 if (frames[i] instanceof AppJmol)
2568 GStructureViewer af = (GStructureViewer) frames[i];
2572 if (avp.size() == 0)
2576 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2581 * Add Groovy Support to Jalview
2584 public void groovyShell_actionPerformed()
2588 openGroovyConsole();
2589 } catch (Exception ex)
2591 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2592 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2594 MessageManager.getString("label.couldnt_create_groovy_shell"),
2595 MessageManager.getString("label.groovy_support_failed"),
2596 JvOptionPane.ERROR_MESSAGE);
2601 * Open the Groovy console
2603 void openGroovyConsole()
2605 if (groovyConsole == null)
2607 groovyConsole = new groovy.ui.Console();
2608 groovyConsole.setVariable("Jalview", this);
2609 groovyConsole.run();
2612 * We allow only one console at a time, so that AlignFrame menu option
2613 * 'Calculate | Run Groovy script' is unambiguous.
2614 * Disable 'Groovy Console', and enable 'Run script', when the console is
2615 * opened, and the reverse when it is closed
2617 Window window = (Window) groovyConsole.getFrame();
2618 window.addWindowListener(new WindowAdapter()
2621 public void windowClosed(WindowEvent e)
2624 * rebind CMD-Q from Groovy Console to Jalview Quit
2627 enableExecuteGroovy(false);
2633 * show Groovy console window (after close and reopen)
2635 ((Window) groovyConsole.getFrame()).setVisible(true);
2638 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2639 * and disable opening a second console
2641 enableExecuteGroovy(true);
2645 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2646 * binding when opened
2648 protected void addQuitHandler()
2650 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2651 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2652 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2654 getRootPane().getActionMap().put("Quit", new AbstractAction()
2657 public void actionPerformed(ActionEvent e)
2665 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2668 * true if Groovy console is open
2670 public void enableExecuteGroovy(boolean enabled)
2673 * disable opening a second Groovy console
2674 * (or re-enable when the console is closed)
2676 groovyShell.setEnabled(!enabled);
2678 AlignFrame[] alignFrames = getAlignFrames();
2679 if (alignFrames != null)
2681 for (AlignFrame af : alignFrames)
2683 af.setGroovyEnabled(enabled);
2689 * Progress bars managed by the IProgressIndicator method.
2691 private Hashtable<Long, JPanel> progressBars;
2693 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2698 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2701 public void setProgressBar(String message, long id)
2703 if (progressBars == null)
2705 progressBars = new Hashtable<>();
2706 progressBarHandlers = new Hashtable<>();
2709 if (progressBars.get(new Long(id)) != null)
2711 JPanel panel = progressBars.remove(new Long(id));
2712 if (progressBarHandlers.contains(new Long(id)))
2714 progressBarHandlers.remove(new Long(id));
2716 removeProgressPanel(panel);
2720 progressBars.put(new Long(id), addProgressPanel(message));
2727 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2728 * jalview.gui.IProgressIndicatorHandler)
2731 public void registerHandler(final long id,
2732 final IProgressIndicatorHandler handler)
2734 if (progressBarHandlers == null
2735 || !progressBars.containsKey(new Long(id)))
2737 throw new Error(MessageManager.getString(
2738 "error.call_setprogressbar_before_registering_handler"));
2740 progressBarHandlers.put(new Long(id), handler);
2741 final JPanel progressPanel = progressBars.get(new Long(id));
2742 if (handler.canCancel())
2744 JButton cancel = new JButton(
2745 MessageManager.getString("action.cancel"));
2746 final IProgressIndicator us = this;
2747 cancel.addActionListener(new ActionListener()
2751 public void actionPerformed(ActionEvent e)
2753 handler.cancelActivity(id);
2754 us.setProgressBar(MessageManager
2755 .formatMessage("label.cancelled_params", new Object[]
2756 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2760 progressPanel.add(cancel, BorderLayout.EAST);
2766 * @return true if any progress bars are still active
2769 public boolean operationInProgress()
2771 if (progressBars != null && progressBars.size() > 0)
2779 * This will return the first AlignFrame holding the given viewport instance.
2780 * It will break if there are more than one AlignFrames viewing a particular
2784 * @return alignFrame for viewport
2786 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2788 if (desktop != null)
2790 AlignmentPanel[] aps = getAlignmentPanels(
2791 viewport.getSequenceSetId());
2792 for (int panel = 0; aps != null && panel < aps.length; panel++)
2794 if (aps[panel] != null && aps[panel].av == viewport)
2796 return aps[panel].alignFrame;
2803 public VamsasApplication getVamsasApplication()
2810 * flag set if jalview GUI is being operated programmatically
2812 private boolean inBatchMode = false;
2815 * check if jalview GUI is being operated programmatically
2817 * @return inBatchMode
2819 public boolean isInBatchMode()
2825 * set flag if jalview GUI is being operated programmatically
2827 * @param inBatchMode
2829 public void setInBatchMode(boolean inBatchMode)
2831 this.inBatchMode = inBatchMode;
2834 public void startServiceDiscovery()
2836 startServiceDiscovery(false);
2839 public void startServiceDiscovery(boolean blocking)
2841 boolean alive = true;
2842 Thread t0 = null, t1 = null, t2 = null;
2843 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2846 // todo: changesupport handlers need to be transferred
2847 if (discoverer == null)
2849 discoverer = new jalview.ws.jws1.Discoverer();
2850 // register PCS handler for desktop.
2851 discoverer.addPropertyChangeListener(changeSupport);
2853 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2854 // until we phase out completely
2855 (t0 = new Thread(discoverer)).start();
2858 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2860 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2861 .startDiscoverer(changeSupport);
2865 // TODO: do rest service discovery
2874 } catch (Exception e)
2877 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2878 || (t3 != null && t3.isAlive())
2879 || (t0 != null && t0.isAlive());
2885 * called to check if the service discovery process completed successfully.
2889 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2891 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2893 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2894 .getErrorMessages();
2897 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2899 if (serviceChangedDialog == null)
2901 // only run if we aren't already displaying one of these.
2902 addDialogThread(serviceChangedDialog = new Runnable()
2909 * JalviewDialog jd =new JalviewDialog() {
2911 * @Override protected void cancelPressed() { // TODO
2912 * Auto-generated method stub
2914 * }@Override protected void okPressed() { // TODO
2915 * Auto-generated method stub
2917 * }@Override protected void raiseClosed() { // TODO
2918 * Auto-generated method stub
2920 * } }; jd.initDialogFrame(new
2921 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2922 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2923 * + " or mis-configured HTTP proxy settings.<br/>" +
2924 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2926 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2927 * ), true, true, "Web Service Configuration Problem", 450,
2930 * jd.waitForInput();
2932 JvOptionPane.showConfirmDialog(Desktop.desktop,
2933 new JLabel("<html><table width=\"450\"><tr><td>"
2934 + ermsg + "</td></tr></table>"
2935 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2936 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2937 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2938 + " Tools->Preferences dialog box to change them.</p></html>"),
2939 "Web Service Configuration Problem",
2940 JvOptionPane.DEFAULT_OPTION,
2941 JvOptionPane.ERROR_MESSAGE);
2942 serviceChangedDialog = null;
2951 "Errors reported by JABA discovery service. Check web services preferences.\n"
2958 private Runnable serviceChangedDialog = null;
2961 * start a thread to open a URL in the configured browser. Pops up a warning
2962 * dialog to the user if there is an exception when calling out to the browser
2967 public static void showUrl(final String url)
2969 showUrl(url, Desktop.instance);
2973 * Like showUrl but allows progress handler to be specified
2977 * (null) or object implementing IProgressIndicator
2979 public static void showUrl(final String url,
2980 final IProgressIndicator progress)
2982 new Thread(new Runnable()
2989 if (progress != null)
2991 progress.setProgressBar(MessageManager
2992 .formatMessage("status.opening_params", new Object[]
2993 { url }), this.hashCode());
2995 jalview.util.BrowserLauncher.openURL(url);
2996 } catch (Exception ex)
2998 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3000 .getString("label.web_browser_not_found_unix"),
3001 MessageManager.getString("label.web_browser_not_found"),
3002 JvOptionPane.WARNING_MESSAGE);
3004 ex.printStackTrace();
3006 if (progress != null)
3008 progress.setProgressBar(null, this.hashCode());
3014 public static WsParamSetManager wsparamManager = null;
3016 public static ParamManager getUserParameterStore()
3018 if (wsparamManager == null)
3020 wsparamManager = new WsParamSetManager();
3022 return wsparamManager;
3026 * static hyperlink handler proxy method for use by Jalview's internal windows
3030 public static void hyperlinkUpdate(HyperlinkEvent e)
3032 if (e.getEventType() == EventType.ACTIVATED)
3037 url = e.getURL().toString();
3038 Desktop.showUrl(url);
3039 } catch (Exception x)
3043 if (Cache.log != null)
3045 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3050 "Couldn't handle string " + url + " as a URL.");
3053 // ignore any exceptions due to dud links.
3060 * single thread that handles display of dialogs to user.
3062 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3065 * flag indicating if dialogExecutor should try to acquire a permit
3067 private volatile boolean dialogPause = true;
3072 private java.util.concurrent.Semaphore block = new Semaphore(0);
3074 private static groovy.ui.Console groovyConsole;
3077 * add another dialog thread to the queue
3081 public void addDialogThread(final Runnable prompter)
3083 dialogExecutor.submit(new Runnable()
3093 } catch (InterruptedException x)
3098 if (instance == null)
3104 SwingUtilities.invokeAndWait(prompter);
3105 } catch (Exception q)
3107 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3113 public void startDialogQueue()
3115 // set the flag so we don't pause waiting for another permit and semaphore
3116 // the current task to begin
3117 dialogPause = false;
3122 protected void snapShotWindow_actionPerformed(ActionEvent e)
3126 ImageMaker im = new jalview.util.ImageMaker(
3127 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3128 getHeight(), of = new File("Jalview_snapshot"
3129 + System.currentTimeMillis() + ".eps"),
3130 "View of desktop", null, 0, false);
3133 paintAll(im.getGraphics());
3135 } catch (Exception q)
3137 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3141 Cache.log.info("Successfully written snapshot to file "
3142 + of.getAbsolutePath());
3146 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3147 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3148 * and location last time the view was expanded (if any). However it does not
3149 * remember the split pane divider location - this is set to match the
3150 * 'exploding' frame.
3154 public void explodeViews(SplitFrame sf)
3156 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3157 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3158 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3160 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3162 int viewCount = topPanels.size();
3169 * Processing in reverse order works, forwards order leaves the first panels
3170 * not visible. I don't know why!
3172 for (int i = viewCount - 1; i >= 0; i--)
3175 * Make new top and bottom frames. These take over the respective
3176 * AlignmentPanel objects, including their AlignmentViewports, so the
3177 * cdna/protein relationships between the viewports is carried over to the
3180 * explodedGeometry holds the (x, y) position of the previously exploded
3181 * SplitFrame, and the (width, height) of the AlignFrame component
3183 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3184 AlignFrame newTopFrame = new AlignFrame(topPanel);
3185 newTopFrame.setSize(oldTopFrame.getSize());
3186 newTopFrame.setVisible(true);
3187 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3188 .getExplodedGeometry();
3189 if (geometry != null)
3191 newTopFrame.setSize(geometry.getSize());
3194 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3195 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3196 newBottomFrame.setSize(oldBottomFrame.getSize());
3197 newBottomFrame.setVisible(true);
3198 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3199 .getExplodedGeometry();
3200 if (geometry != null)
3202 newBottomFrame.setSize(geometry.getSize());
3205 topPanel.av.setGatherViewsHere(false);
3206 bottomPanel.av.setGatherViewsHere(false);
3207 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3209 if (geometry != null)
3211 splitFrame.setLocation(geometry.getLocation());
3213 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3217 * Clear references to the panels (now relocated in the new SplitFrames)
3218 * before closing the old SplitFrame.
3221 bottomPanels.clear();
3226 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3227 * back into the given SplitFrame as additional views. Note that the gathered
3228 * frames may themselves have multiple views.
3232 public void gatherViews(GSplitFrame source)
3235 * special handling of explodedGeometry for a view within a SplitFrame: - it
3236 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3237 * height) of the AlignFrame component
3239 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3240 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3241 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3242 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3243 myBottomFrame.viewport
3244 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3245 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3246 myTopFrame.viewport.setGatherViewsHere(true);
3247 myBottomFrame.viewport.setGatherViewsHere(true);
3248 String topViewId = myTopFrame.viewport.getSequenceSetId();
3249 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3251 JInternalFrame[] frames = desktop.getAllFrames();
3252 for (JInternalFrame frame : frames)
3254 if (frame instanceof SplitFrame && frame != source)
3256 SplitFrame sf = (SplitFrame) frame;
3257 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3258 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3259 boolean gatherThis = false;
3260 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3262 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3263 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3264 if (topViewId.equals(topPanel.av.getSequenceSetId())
3265 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3268 topPanel.av.setGatherViewsHere(false);
3269 bottomPanel.av.setGatherViewsHere(false);
3270 topPanel.av.setExplodedGeometry(
3271 new Rectangle(sf.getLocation(), topFrame.getSize()));
3272 bottomPanel.av.setExplodedGeometry(
3273 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3274 myTopFrame.addAlignmentPanel(topPanel, false);
3275 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3281 topFrame.getAlignPanels().clear();
3282 bottomFrame.getAlignPanels().clear();
3289 * The dust settles...give focus to the tab we did this from.
3291 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3294 public static groovy.ui.Console getGroovyConsole()
3296 return groovyConsole;
3299 public static void transferFromDropTarget(List<String> files,
3300 List<DataSourceType> protocols, DropTargetDropEvent evt,
3301 Transferable t) throws Exception
3304 DataFlavor uriListFlavor = new DataFlavor(
3305 "text/uri-list;class=java.lang.String");
3306 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3308 // Works on Windows and MacOSX
3309 Cache.log.debug("Drop handled as javaFileListFlavor");
3310 for (Object file : (List) t
3311 .getTransferData(DataFlavor.javaFileListFlavor))
3313 files.add(((File) file).toString());
3314 protocols.add(DataSourceType.FILE);
3319 // Unix like behaviour
3320 boolean added = false;
3322 if (t.isDataFlavorSupported(uriListFlavor))
3324 Cache.log.debug("Drop handled as uriListFlavor");
3325 // This is used by Unix drag system
3326 data = (String) t.getTransferData(uriListFlavor);
3330 // fallback to text: workaround - on OSX where there's a JVM bug
3331 Cache.log.debug("standard URIListFlavor failed. Trying text");
3332 // try text fallback
3333 data = (String) t.getTransferData(
3334 new DataFlavor("text/plain;class=java.lang.String"));
3335 if (Cache.log.isDebugEnabled())
3337 Cache.log.debug("fallback returned " + data);
3340 while (protocols.size() < files.size())
3342 Cache.log.debug("Adding missing FILE protocol for "
3343 + files.get(protocols.size()));
3344 protocols.add(DataSourceType.FILE);
3346 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3347 data, "\r\n"); st.hasMoreTokens();)
3350 String s = st.nextToken();
3351 if (s.startsWith("#"))
3353 // the line is a comment (as per the RFC 2483)
3356 java.net.URI uri = new java.net.URI(s);
3357 if (uri.getScheme().toLowerCase().startsWith("http"))
3359 protocols.add(DataSourceType.URL);
3360 files.add(uri.toString());
3364 // otherwise preserve old behaviour: catch all for file objects
3365 java.io.File file = new java.io.File(uri);
3366 protocols.add(DataSourceType.FILE);
3367 files.add(file.toString());
3370 if (Cache.log.isDebugEnabled())
3372 if (data == null || !added)
3375 "Couldn't resolve drop data. Here are the supported flavors:");
3376 for (DataFlavor fl : t.getTransferDataFlavors())
3379 "Supported transfer dataflavor: " + fl.toString());
3380 Object df = t.getTransferData(fl);
3383 Cache.log.debug("Retrieves: " + df);
3387 Cache.log.debug("Retrieved nothing");
3396 * Sets the Preferences property for experimental features to True or False
3397 * depending on the state of the controlling menu item
3400 protected void showExperimental_actionPerformed(boolean selected)
3402 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));