2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.io.DataSourceType;
30 import jalview.io.FileFormat;
31 import jalview.io.FileFormatException;
32 import jalview.io.FileFormatI;
33 import jalview.io.FileFormats;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.urls.IdOrgSettings;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.util.UrlConstants;
46 import jalview.viewmodel.AlignmentViewport;
47 import jalview.ws.params.ParamManager;
48 import jalview.ws.utils.UrlDownloadClient;
50 import java.awt.BorderLayout;
51 import java.awt.Color;
52 import java.awt.Dimension;
53 import java.awt.FontMetrics;
54 import java.awt.Graphics;
55 import java.awt.GridLayout;
56 import java.awt.Point;
57 import java.awt.Rectangle;
58 import java.awt.Toolkit;
59 import java.awt.Window;
60 import java.awt.datatransfer.Clipboard;
61 import java.awt.datatransfer.ClipboardOwner;
62 import java.awt.datatransfer.DataFlavor;
63 import java.awt.datatransfer.Transferable;
64 import java.awt.dnd.DnDConstants;
65 import java.awt.dnd.DropTargetDragEvent;
66 import java.awt.dnd.DropTargetDropEvent;
67 import java.awt.dnd.DropTargetEvent;
68 import java.awt.dnd.DropTargetListener;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.KeyEvent;
72 import java.awt.event.MouseAdapter;
73 import java.awt.event.MouseEvent;
74 import java.awt.event.WindowAdapter;
75 import java.awt.event.WindowEvent;
76 import java.beans.PropertyChangeEvent;
77 import java.beans.PropertyChangeListener;
78 import java.io.BufferedInputStream;
80 import java.io.FileOutputStream;
81 import java.io.IOException;
83 import java.util.ArrayList;
84 import java.util.Hashtable;
85 import java.util.List;
86 import java.util.ListIterator;
87 import java.util.StringTokenizer;
88 import java.util.Vector;
89 import java.util.concurrent.ExecutorService;
90 import java.util.concurrent.Executors;
91 import java.util.concurrent.Semaphore;
93 import javax.swing.AbstractAction;
94 import javax.swing.Box;
95 import javax.swing.BoxLayout;
96 import javax.swing.DefaultDesktopManager;
97 import javax.swing.DesktopManager;
98 import javax.swing.JButton;
99 import javax.swing.JCheckBox;
100 import javax.swing.JComboBox;
101 import javax.swing.JComponent;
102 import javax.swing.JDesktopPane;
103 import javax.swing.JFrame;
104 import javax.swing.JInternalFrame;
105 import javax.swing.JLabel;
106 import javax.swing.JMenuItem;
107 import javax.swing.JPanel;
108 import javax.swing.JPopupMenu;
109 import javax.swing.JProgressBar;
110 import javax.swing.KeyStroke;
111 import javax.swing.SwingUtilities;
112 import javax.swing.event.HyperlinkEvent;
113 import javax.swing.event.HyperlinkEvent.EventType;
114 import javax.swing.event.InternalFrameAdapter;
115 import javax.swing.event.InternalFrameEvent;
116 import javax.swing.event.MenuEvent;
117 import javax.swing.event.MenuListener;
124 * @version $Revision: 1.155 $
126 public class Desktop extends jalview.jbgui.GDesktop
127 implements DropTargetListener, ClipboardOwner, IProgressIndicator,
128 jalview.api.StructureSelectionManagerProvider
130 private static int DEFAULT_MIN_WIDTH = 300;
132 private static int DEFAULT_MIN_HEIGHT = 250;
134 private static int ALIGN_FRAME_DEFAULT_MIN_WIDTH = 600;
136 private static int ALIGN_FRAME_DEFAULT_MIN_HEIGHT = 70;
138 private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
140 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
143 * news reader - null if it was never started.
145 private BlogReader jvnews = null;
147 private File projectFile;
151 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
153 public void addJalviewPropertyChangeListener(
154 PropertyChangeListener listener)
156 changeSupport.addJalviewPropertyChangeListener(listener);
160 * @param propertyName
162 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
163 * java.beans.PropertyChangeListener)
165 public void addJalviewPropertyChangeListener(String propertyName,
166 PropertyChangeListener listener)
168 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
172 * @param propertyName
174 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
175 * java.beans.PropertyChangeListener)
177 public void removeJalviewPropertyChangeListener(String propertyName,
178 PropertyChangeListener listener)
180 changeSupport.removeJalviewPropertyChangeListener(propertyName,
184 /** Singleton Desktop instance */
185 public static Desktop instance;
187 public static MyDesktopPane desktop;
189 static int openFrameCount = 0;
191 static final int xOffset = 30;
193 static final int yOffset = 30;
195 public static jalview.ws.jws1.Discoverer discoverer;
197 public static Object[] jalviewClipboard;
199 public static boolean internalCopy = false;
201 static int fileLoadingCount = 0;
203 class MyDesktopManager implements DesktopManager
206 private DesktopManager delegate;
208 public MyDesktopManager(DesktopManager delegate)
210 this.delegate = delegate;
214 public void activateFrame(JInternalFrame f)
218 delegate.activateFrame(f);
219 } catch (NullPointerException npe)
221 Point p = getMousePosition();
222 instance.showPasteMenu(p.x, p.y);
227 public void beginDraggingFrame(JComponent f)
229 delegate.beginDraggingFrame(f);
233 public void beginResizingFrame(JComponent f, int direction)
235 delegate.beginResizingFrame(f, direction);
239 public void closeFrame(JInternalFrame f)
241 delegate.closeFrame(f);
245 public void deactivateFrame(JInternalFrame f)
247 delegate.deactivateFrame(f);
251 public void deiconifyFrame(JInternalFrame f)
253 delegate.deiconifyFrame(f);
257 public void dragFrame(JComponent f, int newX, int newY)
263 delegate.dragFrame(f, newX, newY);
267 public void endDraggingFrame(JComponent f)
269 delegate.endDraggingFrame(f);
274 public void endResizingFrame(JComponent f)
276 delegate.endResizingFrame(f);
281 public void iconifyFrame(JInternalFrame f)
283 delegate.iconifyFrame(f);
287 public void maximizeFrame(JInternalFrame f)
289 delegate.maximizeFrame(f);
293 public void minimizeFrame(JInternalFrame f)
295 delegate.minimizeFrame(f);
299 public void openFrame(JInternalFrame f)
301 delegate.openFrame(f);
305 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
312 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
316 public void setBoundsForFrame(JComponent f, int newX, int newY,
317 int newWidth, int newHeight)
319 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
322 // All other methods, simply delegate
327 * Creates a new Desktop object.
332 * A note to implementors. It is ESSENTIAL that any activities that might
333 * block are spawned off as threads rather than waited for during this
337 doVamsasClientCheck();
339 doConfigureStructurePrefs();
340 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
341 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
342 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
344 boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
346 desktop = new MyDesktopPane(selmemusage);
347 showMemusage.setSelected(selmemusage);
348 desktop.setBackground(Color.white);
349 getContentPane().setLayout(new BorderLayout());
350 // alternate config - have scrollbars - see notes in JAL-153
351 // JScrollPane sp = new JScrollPane();
352 // sp.getViewport().setView(desktop);
353 // getContentPane().add(sp, BorderLayout.CENTER);
354 getContentPane().add(desktop, BorderLayout.CENTER);
355 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
357 // This line prevents Windows Look&Feel resizing all new windows to maximum
358 // if previous window was maximised
359 desktop.setDesktopManager(
360 new MyDesktopManager(
361 (Platform.isWindows() ? new DefaultDesktopManager()
363 ? new AquaInternalFrameManager(
364 desktop.getDesktopManager())
365 : desktop.getDesktopManager())));
367 Rectangle dims = getLastKnownDimensions("");
374 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
375 setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
378 jconsole = new Console(this, showjconsole);
379 // add essential build information
381 "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
382 + "\n" + "Jalview Installation: "
383 + jalview.bin.Cache.getDefault("INSTALLATION",
385 + "\n" + "Build Date: "
386 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
387 + "\n" + "Java version: "
388 + System.getProperty("java.version") + "\n"
389 + System.getProperty("os.arch") + " "
390 + System.getProperty("os.name") + " "
391 + System.getProperty("os.version"));
393 showConsole(showjconsole);
395 showNews.setVisible(false);
397 experimentalFeatures.setSelected(showExperimental());
399 getIdentifiersOrgData();
403 this.addWindowListener(new WindowAdapter()
406 public void windowClosing(WindowEvent evt)
413 this.addMouseListener(ma = new MouseAdapter()
416 public void mousePressed(MouseEvent evt)
418 if (evt.isPopupTrigger()) // Mac
420 showPasteMenu(evt.getX(), evt.getY());
425 public void mouseReleased(MouseEvent evt)
427 if (evt.isPopupTrigger()) // Windows
429 showPasteMenu(evt.getX(), evt.getY());
433 desktop.addMouseListener(ma);
435 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
436 // Spawn a thread that shows the splashscreen
437 SwingUtilities.invokeLater(new Runnable()
446 // Thread off a new instance of the file chooser - this reduces the time it
447 // takes to open it later on.
448 new Thread(new Runnable()
453 Cache.log.debug("Filechooser init thread started.");
454 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
455 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
457 Cache.log.debug("Filechooser init thread finished.");
460 // Add the service change listener
461 changeSupport.addJalviewPropertyChangeListener("services",
462 new PropertyChangeListener()
466 public void propertyChange(PropertyChangeEvent evt)
468 Cache.log.debug("Firing service changed event for "
469 + evt.getNewValue());
470 JalviewServicesChanged(evt);
477 * Answers true if user preferences to enable experimental features is True
482 public boolean showExperimental()
484 String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
485 Boolean.FALSE.toString());
486 return Boolean.valueOf(experimental).booleanValue();
489 public void doConfigureStructurePrefs()
491 // configure services
492 StructureSelectionManager ssm = StructureSelectionManager
493 .getStructureSelectionManager(this);
494 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
496 ssm.setAddTempFacAnnot(jalview.bin.Cache
497 .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
498 ssm.setProcessSecondaryStructure(jalview.bin.Cache
499 .getDefault(Preferences.STRUCT_FROM_PDB, true));
500 ssm.setSecStructServices(
501 jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
505 ssm.setAddTempFacAnnot(false);
506 ssm.setProcessSecondaryStructure(false);
507 ssm.setSecStructServices(false);
511 public void checkForNews()
513 final Desktop me = this;
514 // Thread off the news reader, in case there are connection problems.
515 addDialogThread(new Runnable()
520 Cache.log.debug("Starting news thread.");
522 jvnews = new BlogReader(me);
523 showNews.setVisible(true);
524 Cache.log.debug("Completed news thread.");
529 public void getIdentifiersOrgData()
531 // Thread off the identifiers fetcher
532 addDialogThread(new Runnable()
537 Cache.log.debug("Downloading data from identifiers.org");
538 UrlDownloadClient client = new UrlDownloadClient();
541 client.download(IdOrgSettings.getUrl(),
542 IdOrgSettings.getDownloadLocation());
543 } catch (IOException e)
545 Cache.log.debug("Exception downloading identifiers.org data"
553 protected void showNews_actionPerformed(ActionEvent e)
555 showNews(showNews.isSelected());
558 void showNews(boolean visible)
561 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
562 showNews.setSelected(visible);
563 if (visible && !jvnews.isVisible())
565 new Thread(new Runnable()
570 long now = System.currentTimeMillis();
571 Desktop.instance.setProgressBar(
572 MessageManager.getString("status.refreshing_news"),
574 jvnews.refreshNews();
575 Desktop.instance.setProgressBar(null, now);
584 * recover the last known dimensions for a jalview window
587 * - empty string is desktop, all other windows have unique prefix
588 * @return null or last known dimensions scaled to current geometry (if last
589 * window geom was known)
591 Rectangle getLastKnownDimensions(String windowName)
593 // TODO: lock aspect ratio for scaling desktop Bug #0058199
594 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
595 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
596 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
597 String width = jalview.bin.Cache
598 .getProperty(windowName + "SCREEN_WIDTH");
599 String height = jalview.bin.Cache
600 .getProperty(windowName + "SCREEN_HEIGHT");
601 if ((x != null) && (y != null) && (width != null) && (height != null))
603 int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
604 iw = Integer.parseInt(width), ih = Integer.parseInt(height);
605 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
607 // attempt #1 - try to cope with change in screen geometry - this
608 // version doesn't preserve original jv aspect ratio.
609 // take ratio of current screen size vs original screen size.
610 double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
611 jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
612 double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
613 jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
614 // rescale the bounds depending upon the current screen geometry.
615 ix = (int) (ix * sw);
616 iw = (int) (iw * sw);
617 iy = (int) (iy * sh);
618 ih = (int) (ih * sh);
619 while (ix >= screenSize.width)
621 jalview.bin.Cache.log.debug(
622 "Window geometry location recall error: shifting horizontal to within screenbounds.");
623 ix -= screenSize.width;
625 while (iy >= screenSize.height)
627 jalview.bin.Cache.log.debug(
628 "Window geometry location recall error: shifting vertical to within screenbounds.");
629 iy -= screenSize.height;
631 jalview.bin.Cache.log.debug(
632 "Got last known dimensions for " + windowName + ": x:" + ix
633 + " y:" + iy + " width:" + iw + " height:" + ih);
635 // return dimensions for new instance
636 return new Rectangle(ix, iy, iw, ih);
641 private void doVamsasClientCheck()
643 if (jalview.bin.Cache.vamsasJarsPresent())
645 setupVamsasDisconnectedGui();
646 VamsasMenu.setVisible(true);
647 final Desktop us = this;
648 VamsasMenu.addMenuListener(new MenuListener()
650 // this listener remembers when the menu was first selected, and
651 // doesn't rebuild the session list until it has been cleared and
653 boolean refresh = true;
656 public void menuCanceled(MenuEvent e)
662 public void menuDeselected(MenuEvent e)
668 public void menuSelected(MenuEvent e)
672 us.buildVamsasStMenu();
677 vamsasStart.setVisible(true);
681 void showPasteMenu(int x, int y)
683 JPopupMenu popup = new JPopupMenu();
684 JMenuItem item = new JMenuItem(
685 MessageManager.getString("label.paste_new_window"));
686 item.addActionListener(new ActionListener()
689 public void actionPerformed(ActionEvent evt)
696 popup.show(this, x, y);
703 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
704 Transferable contents = c.getContents(this);
706 if (contents != null)
708 String file = (String) contents
709 .getTransferData(DataFlavor.stringFlavor);
711 FileFormatI format = new IdentifyFile().identify(file,
712 DataSourceType.PASTE);
714 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
717 } catch (Exception ex)
720 "Unable to paste alignment from system clipboard:\n" + ex);
725 * Adds and opens the given frame to the desktop
736 public static synchronized void addInternalFrame(
737 final JInternalFrame frame, String title, int w, int h)
739 addInternalFrame(frame, title, true, w, h, true, false);
743 * Add an internal frame to the Jalview desktop
750 * When true, display frame immediately, otherwise, caller must call
751 * setVisible themselves.
757 public static synchronized void addInternalFrame(
758 final JInternalFrame frame, String title, boolean makeVisible,
761 addInternalFrame(frame, title, makeVisible, w, h, true, false);
765 * Add an internal frame to the Jalview desktop and make it visible
778 public static synchronized void addInternalFrame(
779 final JInternalFrame frame, String title, int w, int h,
782 addInternalFrame(frame, title, true, w, h, resizable, false);
786 * Add an internal frame to the Jalview desktop
793 * When true, display frame immediately, otherwise, caller must call
794 * setVisible themselves.
801 * @param ignoreMinSize
802 * Do not set the default minimum size for frame
804 public static synchronized void addInternalFrame(
805 final JInternalFrame frame, String title, boolean makeVisible,
806 int w, int h, boolean resizable, boolean ignoreMinSize)
809 // TODO: allow callers to determine X and Y position of frame (eg. via
811 // TODO: consider fixing method to update entries in the window submenu with
812 // the current window title
814 frame.setTitle(title);
815 if (frame.getWidth() < 1 || frame.getHeight() < 1)
819 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
820 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
821 // IF JALVIEW IS RUNNING HEADLESS
822 // ///////////////////////////////////////////////
823 if (instance == null || (System.getProperty("java.awt.headless") != null
824 && System.getProperty("java.awt.headless").equals("true")))
833 frame.setMinimumSize(
834 new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
836 // Set default dimension for Alignment Frame window.
837 // The Alignment Frame window could be added from a number of places,
839 // I did this here in order not to miss out on any Alignment frame.
840 if (frame instanceof AlignFrame)
842 frame.setMinimumSize(new Dimension(ALIGN_FRAME_DEFAULT_MIN_WIDTH,
843 ALIGN_FRAME_DEFAULT_MIN_HEIGHT));
847 frame.setVisible(makeVisible);
848 frame.setClosable(true);
849 frame.setResizable(resizable);
850 frame.setMaximizable(resizable);
851 frame.setIconifiable(resizable);
852 frame.setOpaque(false);
854 if (frame.getX() < 1 && frame.getY() < 1)
856 frame.setLocation(xOffset * openFrameCount,
857 yOffset * ((openFrameCount - 1) % 10) + yOffset);
861 * add an entry for the new frame in the Window menu
862 * (and remove it when the frame is closed)
864 final JMenuItem menuItem = new JMenuItem(title);
865 frame.addInternalFrameListener(new InternalFrameAdapter()
868 public void internalFrameActivated(InternalFrameEvent evt)
870 JInternalFrame itf = desktop.getSelectedFrame();
873 if (itf instanceof AlignFrame)
875 Jalview.setCurrentAlignFrame((AlignFrame) itf);
882 public void internalFrameClosed(InternalFrameEvent evt)
884 PaintRefresher.RemoveComponent(frame);
887 * defensive check to prevent frames being
888 * added half off the window
890 if (openFrameCount > 0)
896 * ensure no reference to alignFrame retained by menu item listener
898 if (menuItem.getActionListeners().length > 0)
900 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
902 windowMenu.remove(menuItem);
906 menuItem.addActionListener(new ActionListener()
909 public void actionPerformed(ActionEvent e)
913 frame.setSelected(true);
914 frame.setIcon(false);
915 } catch (java.beans.PropertyVetoException ex)
924 windowMenu.add(menuItem);
929 frame.setSelected(true);
930 frame.requestFocus();
931 } catch (java.beans.PropertyVetoException ve)
933 } catch (java.lang.ClassCastException cex)
936 "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
942 public void lostOwnership(Clipboard clipboard, Transferable contents)
946 Desktop.jalviewClipboard = null;
949 internalCopy = false;
953 public void dragEnter(DropTargetDragEvent evt)
958 public void dragExit(DropTargetEvent evt)
963 public void dragOver(DropTargetDragEvent evt)
968 public void dropActionChanged(DropTargetDragEvent evt)
979 public void drop(DropTargetDropEvent evt)
981 boolean success = true;
982 // JAL-1552 - acceptDrop required before getTransferable call for
983 // Java's Transferable for native dnd
984 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
985 Transferable t = evt.getTransferable();
986 List<String> files = new ArrayList<>();
987 List<DataSourceType> protocols = new ArrayList<>();
991 Desktop.transferFromDropTarget(files, protocols, evt, t);
992 } catch (Exception e)
1002 for (int i = 0; i < files.size(); i++)
1004 String file = files.get(i).toString();
1005 DataSourceType protocol = (protocols == null)
1006 ? DataSourceType.FILE
1008 FileFormatI format = null;
1010 if (file.endsWith(".jar"))
1012 format = FileFormat.Jalview;
1017 format = new IdentifyFile().identify(file, protocol);
1020 new FileLoader().LoadFile(file, protocol, format);
1023 } catch (Exception ex)
1028 evt.dropComplete(success); // need this to ensure input focus is properly
1029 // transfered to any new windows created
1039 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1041 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1042 JalviewFileChooser chooser = JalviewFileChooser
1043 .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1045 chooser.setFileView(new JalviewFileView());
1046 chooser.setDialogTitle(
1047 MessageManager.getString("label.open_local_file"));
1048 chooser.setToolTipText(MessageManager.getString("action.open"));
1050 int value = chooser.showOpenDialog(this);
1052 if (value == JalviewFileChooser.APPROVE_OPTION)
1054 String choice = chooser.getSelectedFile().getPath();
1055 Cache.setProperty("LAST_DIRECTORY",
1056 chooser.getSelectedFile().getParent());
1058 FileFormatI format = chooser.getSelectedFormat();
1061 * Call IdentifyFile to verify the file contains what its extension implies.
1062 * Skip this step for dynamically added file formats, because
1063 * IdentifyFile does not know how to recognise them.
1065 if (FileFormats.getInstance().isIdentifiable(format))
1069 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1070 } catch (FileFormatException e)
1072 // format = null; //??
1076 if (viewport != null)
1078 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1083 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1095 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1097 // This construct allows us to have a wider textfield
1099 JLabel label = new JLabel(
1100 MessageManager.getString("label.input_file_url"));
1101 final JComboBox history = new JComboBox();
1103 JPanel panel = new JPanel(new GridLayout(2, 1));
1106 history.setPreferredSize(new Dimension(400, 20));
1107 history.setEditable(true);
1108 history.addItem("http://www.");
1110 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1114 if (historyItems != null)
1116 st = new StringTokenizer(historyItems, "\t");
1118 while (st.hasMoreTokens())
1120 history.addItem(st.nextElement());
1124 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1125 MessageManager.getString("label.input_alignment_from_url"),
1126 JvOptionPane.OK_CANCEL_OPTION);
1128 if (reply != JvOptionPane.OK_OPTION)
1133 String url = history.getSelectedItem().toString();
1135 if (url.toLowerCase().endsWith(".jar"))
1137 if (viewport != null)
1139 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1140 FileFormat.Jalview);
1144 new FileLoader().LoadFile(url, DataSourceType.URL,
1145 FileFormat.Jalview);
1150 FileFormatI format = null;
1153 format = new IdentifyFile().identify(url, DataSourceType.URL);
1154 } catch (FileFormatException e)
1156 // TODO revise error handling, distinguish between
1157 // URL not found and response not valid
1162 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1163 MessageManager.formatMessage("label.couldnt_locate",
1166 MessageManager.getString("label.url_not_found"),
1167 JvOptionPane.WARNING_MESSAGE);
1172 if (viewport != null)
1174 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1179 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1185 * Opens the CutAndPaste window for the user to paste an alignment in to
1188 * - if not null, the pasted alignment is added to the current
1189 * alignment; if null, to a new alignment window
1192 public void inputTextboxMenuItem_actionPerformed(
1193 AlignmentViewPanel viewPanel)
1195 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1196 cap.setForInput(viewPanel);
1197 Desktop.addInternalFrame(cap,
1198 MessageManager.getString("label.cut_paste_alignmen_file"), true,
1208 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1209 jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
1211 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
1212 screen.height + "");
1213 storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
1214 getWidth(), getHeight()));
1216 if (jconsole != null)
1218 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1219 jconsole.stopConsole();
1223 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1226 if (dialogExecutor != null)
1228 dialogExecutor.shutdownNow();
1230 closeAll_actionPerformed(null);
1232 if (groovyConsole != null)
1234 // suppress a possible repeat prompt to save script
1235 groovyConsole.setDirty(false);
1236 groovyConsole.exit();
1241 private void storeLastKnownDimensions(String string, Rectangle jc)
1243 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1244 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1245 + " height:" + jc.height);
1247 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1248 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1249 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1250 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1260 public void aboutMenuItem_actionPerformed(ActionEvent e)
1262 // StringBuffer message = getAboutMessage(false);
1263 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1265 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1266 new Thread(new Runnable()
1271 new SplashScreen(true);
1276 public StringBuffer getAboutMessage(boolean shortv)
1278 StringBuffer message = new StringBuffer();
1279 message.append("<html>");
1282 message.append("<h1><strong>Version: "
1283 + jalview.bin.Cache.getProperty("VERSION")
1284 + "</strong></h1>");
1285 message.append("<strong>Last Updated: <em>"
1286 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1287 + "</em></strong>");
1293 message.append("<strong>Version "
1294 + jalview.bin.Cache.getProperty("VERSION")
1295 + "; last updated: "
1296 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1299 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1300 .equals("Checking"))
1302 message.append("<br>...Checking latest version...</br>");
1304 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1305 .equals(jalview.bin.Cache.getProperty("VERSION")))
1307 boolean red = false;
1308 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1309 .indexOf("automated build") == -1)
1312 // Displayed when code version and jnlp version do not match and code
1313 // version is not a development build
1314 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1317 message.append("<br>!! Version "
1318 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1320 + " is available for download from "
1321 + jalview.bin.Cache.getDefault("www.jalview.org",
1322 "http://www.jalview.org")
1326 message.append("</div>");
1329 message.append("<br>Authors: " + jalview.bin.Cache.getDefault(
1331 "The Jalview Authors (See AUTHORS file for current list)")
1332 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1333 + "<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"
1334 + "<br><br>If you use Jalview, please cite:"
1335 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1336 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1337 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1349 public void documentationMenuItem_actionPerformed(ActionEvent e)
1353 Help.showHelpWindow();
1354 } catch (Exception ex)
1360 public void closeAll_actionPerformed(ActionEvent e)
1362 // TODO show a progress bar while closing?
1363 JInternalFrame[] frames = desktop.getAllFrames();
1364 for (int i = 0; i < frames.length; i++)
1368 frames[i].setClosed(true);
1369 } catch (java.beans.PropertyVetoException ex)
1373 Jalview.setCurrentAlignFrame(null);
1374 System.out.println("ALL CLOSED");
1375 if (v_client != null)
1377 // TODO clear binding to vamsas document objects on close_all
1381 * reset state of singleton objects as appropriate (clear down session state
1382 * when all windows are closed)
1384 StructureSelectionManager ssm = StructureSelectionManager
1385 .getStructureSelectionManager(this);
1393 public void raiseRelated_actionPerformed(ActionEvent e)
1395 reorderAssociatedWindows(false, false);
1399 public void minimizeAssociated_actionPerformed(ActionEvent e)
1401 reorderAssociatedWindows(true, false);
1404 void closeAssociatedWindows()
1406 reorderAssociatedWindows(false, true);
1412 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1416 protected void garbageCollect_actionPerformed(ActionEvent e)
1418 // We simply collect the garbage
1419 jalview.bin.Cache.log.debug("Collecting garbage...");
1421 jalview.bin.Cache.log.debug("Finished garbage collection.");
1428 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1432 protected void showMemusage_actionPerformed(ActionEvent e)
1434 desktop.showMemoryUsage(showMemusage.isSelected());
1441 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1445 protected void showConsole_actionPerformed(ActionEvent e)
1447 showConsole(showConsole.isSelected());
1450 Console jconsole = null;
1453 * control whether the java console is visible or not
1457 void showConsole(boolean selected)
1459 showConsole.setSelected(selected);
1460 // TODO: decide if we should update properties file
1461 Cache.setProperty("SHOW_JAVA_CONSOLE",
1462 Boolean.valueOf(selected).toString());
1463 jconsole.setVisible(selected);
1466 void reorderAssociatedWindows(boolean minimize, boolean close)
1468 JInternalFrame[] frames = desktop.getAllFrames();
1469 if (frames == null || frames.length < 1)
1474 AlignmentViewport source = null, target = null;
1475 if (frames[0] instanceof AlignFrame)
1477 source = ((AlignFrame) frames[0]).getCurrentView();
1479 else if (frames[0] instanceof TreePanel)
1481 source = ((TreePanel) frames[0]).getViewPort();
1483 else if (frames[0] instanceof PCAPanel)
1485 source = ((PCAPanel) frames[0]).av;
1487 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1489 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1494 for (int i = 0; i < frames.length; i++)
1497 if (frames[i] == null)
1501 if (frames[i] instanceof AlignFrame)
1503 target = ((AlignFrame) frames[i]).getCurrentView();
1505 else if (frames[i] instanceof TreePanel)
1507 target = ((TreePanel) frames[i]).getViewPort();
1509 else if (frames[i] instanceof PCAPanel)
1511 target = ((PCAPanel) frames[i]).av;
1513 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1515 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1518 if (source == target)
1524 frames[i].setClosed(true);
1528 frames[i].setIcon(minimize);
1531 frames[i].toFront();
1535 } catch (java.beans.PropertyVetoException ex)
1550 protected void preferences_actionPerformed(ActionEvent e)
1562 public void saveState_actionPerformed(ActionEvent e)
1564 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1567 chooser.setFileView(new JalviewFileView());
1568 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1570 int value = chooser.showSaveDialog(this);
1572 if (value == JalviewFileChooser.APPROVE_OPTION)
1574 final Desktop me = this;
1575 final java.io.File choice = chooser.getSelectedFile();
1576 setProjectFile(choice);
1578 new Thread(new Runnable()
1583 // TODO: refactor to Jalview desktop session controller action.
1584 setProgressBar(MessageManager.formatMessage(
1585 "label.saving_jalview_project", new Object[]
1586 { choice.getName() }), choice.hashCode());
1587 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1588 choice.getParent());
1589 // TODO catch and handle errors for savestate
1590 // TODO prevent user from messing with the Desktop whilst we're saving
1593 new Jalview2XML().saveState(choice);
1594 } catch (OutOfMemoryError oom)
1597 "Whilst saving current state to " + choice.getName(),
1599 } catch (Exception ex)
1602 "Problems whilst trying to save to " + choice.getName(),
1604 JvOptionPane.showMessageDialog(me,
1605 MessageManager.formatMessage(
1606 "label.error_whilst_saving_current_state_to",
1608 { choice.getName() }),
1609 MessageManager.getString("label.couldnt_save_project"),
1610 JvOptionPane.WARNING_MESSAGE);
1612 setProgressBar(null, choice.hashCode());
1618 private void setProjectFile(File choice)
1620 this.projectFile = choice;
1623 public File getProjectFile()
1625 return this.projectFile;
1635 public void loadState_actionPerformed(ActionEvent e)
1637 JalviewFileChooser chooser = new JalviewFileChooser(
1638 Cache.getProperty("LAST_DIRECTORY"), new String[]
1641 { "Jalview Project", "Jalview Project (old)" },
1643 chooser.setFileView(new JalviewFileView());
1644 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1646 int value = chooser.showOpenDialog(this);
1648 if (value == JalviewFileChooser.APPROVE_OPTION)
1650 final File selectedFile = chooser.getSelectedFile();
1651 setProjectFile(selectedFile);
1652 final String choice = selectedFile.getAbsolutePath();
1653 Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
1654 new Thread(new Runnable()
1659 setProgressBar(MessageManager.formatMessage(
1660 "label.loading_jalview_project", new Object[]
1661 { choice }), choice.hashCode());
1664 new Jalview2XML().loadJalviewAlign(choice);
1665 } catch (OutOfMemoryError oom)
1667 new OOMWarning("Whilst loading project from " + choice, oom);
1668 } catch (Exception ex)
1671 "Problems whilst loading project from " + choice, ex);
1672 JvOptionPane.showMessageDialog(Desktop.desktop,
1673 MessageManager.formatMessage(
1674 "label.error_whilst_loading_project_from",
1677 MessageManager.getString("label.couldnt_load_project"),
1678 JvOptionPane.WARNING_MESSAGE);
1680 setProgressBar(null, choice.hashCode());
1687 public void inputSequence_actionPerformed(ActionEvent e)
1689 new SequenceFetcher(this);
1692 JPanel progressPanel;
1694 ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
1696 public void startLoading(final String fileName)
1698 if (fileLoadingCount == 0)
1700 fileLoadingPanels.add(addProgressPanel(MessageManager
1701 .formatMessage("label.loading_file", new Object[]
1707 private JPanel addProgressPanel(String string)
1709 if (progressPanel == null)
1711 progressPanel = new JPanel(new GridLayout(1, 1));
1712 totalProgressCount = 0;
1713 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1715 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1716 JProgressBar progressBar = new JProgressBar();
1717 progressBar.setIndeterminate(true);
1719 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1721 thisprogress.add(progressBar, BorderLayout.CENTER);
1722 progressPanel.add(thisprogress);
1723 ((GridLayout) progressPanel.getLayout()).setRows(
1724 ((GridLayout) progressPanel.getLayout()).getRows() + 1);
1725 ++totalProgressCount;
1726 instance.validate();
1727 return thisprogress;
1730 int totalProgressCount = 0;
1732 private void removeProgressPanel(JPanel progbar)
1734 if (progressPanel != null)
1736 synchronized (progressPanel)
1738 progressPanel.remove(progbar);
1739 GridLayout gl = (GridLayout) progressPanel.getLayout();
1740 gl.setRows(gl.getRows() - 1);
1741 if (--totalProgressCount < 1)
1743 this.getContentPane().remove(progressPanel);
1744 progressPanel = null;
1751 public void stopLoading()
1754 if (fileLoadingCount < 1)
1756 while (fileLoadingPanels.size() > 0)
1758 removeProgressPanel(fileLoadingPanels.remove(0));
1760 fileLoadingPanels.clear();
1761 fileLoadingCount = 0;
1766 public static int getViewCount(String alignmentId)
1768 AlignmentViewport[] aps = getViewports(alignmentId);
1769 return (aps == null) ? 0 : aps.length;
1774 * @param alignmentId
1775 * - if null, all sets are returned
1776 * @return all AlignmentPanels concerning the alignmentId sequence set
1778 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1780 if (Desktop.desktop == null)
1782 // no frames created and in headless mode
1783 // TODO: verify that frames are recoverable when in headless mode
1786 List<AlignmentPanel> aps = new ArrayList<>();
1787 AlignFrame[] frames = getAlignFrames();
1792 for (AlignFrame af : frames)
1794 for (AlignmentPanel ap : af.alignPanels)
1796 if (alignmentId == null
1797 || alignmentId.equals(ap.av.getSequenceSetId()))
1803 if (aps.size() == 0)
1807 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1812 * get all the viewports on an alignment.
1814 * @param sequenceSetId
1815 * unique alignment id (may be null - all viewports returned in that
1817 * @return all viewports on the alignment bound to sequenceSetId
1819 public static AlignmentViewport[] getViewports(String sequenceSetId)
1821 List<AlignmentViewport> viewp = new ArrayList<>();
1822 if (desktop != null)
1824 AlignFrame[] frames = Desktop.getAlignFrames();
1826 for (AlignFrame afr : frames)
1828 if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
1829 .equals(sequenceSetId))
1831 if (afr.alignPanels != null)
1833 for (AlignmentPanel ap : afr.alignPanels)
1835 if (sequenceSetId == null
1836 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1844 viewp.add(afr.getViewport());
1848 if (viewp.size() > 0)
1850 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1857 * Explode the views in the given frame into separate AlignFrame
1861 public static void explodeViews(AlignFrame af)
1863 int size = af.alignPanels.size();
1869 for (int i = 0; i < size; i++)
1871 AlignmentPanel ap = af.alignPanels.get(i);
1872 AlignFrame newaf = new AlignFrame(ap);
1875 * Restore the view's last exploded frame geometry if known. Multiple
1876 * views from one exploded frame share and restore the same (frame)
1877 * position and size.
1879 Rectangle geometry = ap.av.getExplodedGeometry();
1880 if (geometry != null)
1882 newaf.setBounds(geometry);
1885 ap.av.setGatherViewsHere(false);
1887 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1888 AlignFrame.DEFAULT_HEIGHT);
1891 af.alignPanels.clear();
1892 af.closeMenuItem_actionPerformed(true);
1897 * Gather expanded views (separate AlignFrame's) with the same sequence set
1898 * identifier back in to this frame as additional views, and close the
1899 * expanded views. Note the expanded frames may themselves have multiple
1900 * views. We take the lot.
1904 public void gatherViews(AlignFrame source)
1906 source.viewport.setGatherViewsHere(true);
1907 source.viewport.setExplodedGeometry(source.getBounds());
1908 JInternalFrame[] frames = desktop.getAllFrames();
1909 String viewId = source.viewport.getSequenceSetId();
1911 for (int t = 0; t < frames.length; t++)
1913 if (frames[t] instanceof AlignFrame && frames[t] != source)
1915 AlignFrame af = (AlignFrame) frames[t];
1916 boolean gatherThis = false;
1917 for (int a = 0; a < af.alignPanels.size(); a++)
1919 AlignmentPanel ap = af.alignPanels.get(a);
1920 if (viewId.equals(ap.av.getSequenceSetId()))
1923 ap.av.setGatherViewsHere(false);
1924 ap.av.setExplodedGeometry(af.getBounds());
1925 source.addAlignmentPanel(ap, false);
1931 af.alignPanels.clear();
1932 af.closeMenuItem_actionPerformed(true);
1939 jalview.gui.VamsasApplication v_client = null;
1942 public void vamsasImport_actionPerformed(ActionEvent e)
1944 if (v_client == null)
1946 // Load and try to start a session.
1947 JalviewFileChooser chooser = new JalviewFileChooser(
1948 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1950 chooser.setFileView(new JalviewFileView());
1951 chooser.setDialogTitle(
1952 MessageManager.getString("label.open_saved_vamsas_session"));
1953 chooser.setToolTipText(MessageManager.getString(
1954 "label.select_vamsas_session_opened_as_new_vamsas_session"));
1956 int value = chooser.showOpenDialog(this);
1958 if (value == JalviewFileChooser.APPROVE_OPTION)
1960 String fle = chooser.getSelectedFile().toString();
1961 if (!vamsasImport(chooser.getSelectedFile()))
1963 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1964 MessageManager.formatMessage(
1965 "label.couldnt_import_as_vamsas_session",
1969 .getString("label.vamsas_document_import_failed"),
1970 JvOptionPane.ERROR_MESSAGE);
1976 jalview.bin.Cache.log.error(
1977 "Implementation error - load session from a running session is not supported.");
1982 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1985 * @return true if import was a success and a session was started.
1987 public boolean vamsasImport(URL url)
1989 // TODO: create progress bar
1990 if (v_client != null)
1993 jalview.bin.Cache.log.error(
1994 "Implementation error - load session from a running session is not supported.");
2000 // copy the URL content to a temporary local file
2001 // TODO: be a bit cleverer here with nio (?!)
2002 File file = File.createTempFile("vdocfromurl", ".vdj");
2003 FileOutputStream fos = new FileOutputStream(file);
2004 BufferedInputStream bis = new BufferedInputStream(url.openStream());
2005 byte[] buffer = new byte[2048];
2007 while ((ln = bis.read(buffer)) > -1)
2009 fos.write(buffer, 0, ln);
2013 v_client = new jalview.gui.VamsasApplication(this, file,
2014 url.toExternalForm());
2015 } catch (Exception ex)
2017 jalview.bin.Cache.log.error(
2018 "Failed to create new vamsas session from contents of URL "
2023 setupVamsasConnectedGui();
2024 v_client.initial_update(); // TODO: thread ?
2025 return v_client.inSession();
2029 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
2032 * @return true if import was a success and a session was started.
2034 public boolean vamsasImport(File file)
2036 if (v_client != null)
2039 jalview.bin.Cache.log.error(
2040 "Implementation error - load session from a running session is not supported.");
2044 setProgressBar(MessageManager.formatMessage(
2045 "status.importing_vamsas_session_from", new Object[]
2046 { file.getName() }), file.hashCode());
2049 v_client = new jalview.gui.VamsasApplication(this, file, null);
2050 } catch (Exception ex)
2052 setProgressBar(MessageManager.formatMessage(
2053 "status.importing_vamsas_session_from", new Object[]
2054 { file.getName() }), file.hashCode());
2055 jalview.bin.Cache.log.error(
2056 "New vamsas session from existing session file failed:", ex);
2059 setupVamsasConnectedGui();
2060 v_client.initial_update(); // TODO: thread ?
2061 setProgressBar(MessageManager.formatMessage(
2062 "status.importing_vamsas_session_from", new Object[]
2063 { file.getName() }), file.hashCode());
2064 return v_client.inSession();
2067 public boolean joinVamsasSession(String mysesid)
2069 if (v_client != null)
2071 throw new Error(MessageManager
2072 .getString("error.try_join_vamsas_session_another"));
2074 if (mysesid == null)
2077 MessageManager.getString("error.invalid_vamsas_session_id"));
2079 v_client = new VamsasApplication(this, mysesid);
2080 setupVamsasConnectedGui();
2081 v_client.initial_update();
2082 return (v_client.inSession());
2086 public void vamsasStart_actionPerformed(ActionEvent e)
2088 if (v_client == null)
2091 // we just start a default session for moment.
2093 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2094 * getProperty("LAST_DIRECTORY"));
2096 * chooser.setFileView(new JalviewFileView());
2097 * chooser.setDialogTitle("Load Vamsas file");
2098 * chooser.setToolTipText("Import");
2100 * int value = chooser.showOpenDialog(this);
2102 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2103 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2105 v_client = new VamsasApplication(this);
2106 setupVamsasConnectedGui();
2107 v_client.initial_update(); // TODO: thread ?
2111 // store current data in session.
2112 v_client.push_update(); // TODO: thread
2116 protected void setupVamsasConnectedGui()
2118 vamsasStart.setText(MessageManager.getString("label.session_update"));
2119 vamsasSave.setVisible(true);
2120 vamsasStop.setVisible(true);
2121 vamsasImport.setVisible(false); // Document import to existing session is
2122 // not possible for vamsas-client-1.0.
2125 protected void setupVamsasDisconnectedGui()
2127 vamsasSave.setVisible(false);
2128 vamsasStop.setVisible(false);
2129 vamsasImport.setVisible(true);
2131 .setText(MessageManager.getString("label.new_vamsas_session"));
2135 public void vamsasStop_actionPerformed(ActionEvent e)
2137 if (v_client != null)
2139 v_client.end_session();
2141 setupVamsasDisconnectedGui();
2145 protected void buildVamsasStMenu()
2147 if (v_client == null)
2149 String[] sess = null;
2152 sess = VamsasApplication.getSessionList();
2153 } catch (Exception e)
2155 jalview.bin.Cache.log.warn("Problem getting current sessions list.",
2161 jalview.bin.Cache.log.debug(
2162 "Got current sessions list: " + sess.length + " entries.");
2163 VamsasStMenu.removeAll();
2164 for (int i = 0; i < sess.length; i++)
2166 JMenuItem sessit = new JMenuItem();
2167 sessit.setText(sess[i]);
2168 sessit.setToolTipText(MessageManager
2169 .formatMessage("label.connect_to_session", new Object[]
2171 final Desktop dsktp = this;
2172 final String mysesid = sess[i];
2173 sessit.addActionListener(new ActionListener()
2177 public void actionPerformed(ActionEvent e)
2179 if (dsktp.v_client == null)
2181 Thread rthr = new Thread(new Runnable()
2187 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2188 dsktp.setupVamsasConnectedGui();
2189 dsktp.v_client.initial_update();
2197 VamsasStMenu.add(sessit);
2199 // don't show an empty menu.
2200 VamsasStMenu.setVisible(sess.length > 0);
2205 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2206 VamsasStMenu.removeAll();
2207 VamsasStMenu.setVisible(false);
2212 // Not interested in the content. Just hide ourselves.
2213 VamsasStMenu.setVisible(false);
2218 public void vamsasSave_actionPerformed(ActionEvent e)
2220 if (v_client != null)
2222 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2223 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2226 chooser.setFileView(new JalviewFileView());
2227 chooser.setDialogTitle(MessageManager
2228 .getString("label.save_vamsas_document_archive"));
2230 int value = chooser.showSaveDialog(this);
2232 if (value == JalviewFileChooser.APPROVE_OPTION)
2234 java.io.File choice = chooser.getSelectedFile();
2235 JPanel progpanel = addProgressPanel(MessageManager
2236 .formatMessage("label.saving_vamsas_doc", new Object[]
2237 { choice.getName() }));
2238 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2239 String warnmsg = null;
2240 String warnttl = null;
2243 v_client.vclient.storeDocument(choice);
2246 warnttl = "Serious Problem saving Vamsas Document";
2247 warnmsg = ex.toString();
2248 jalview.bin.Cache.log
2249 .error("Error Whilst saving document to " + choice, ex);
2251 } catch (Exception ex)
2253 warnttl = "Problem saving Vamsas Document.";
2254 warnmsg = ex.toString();
2255 jalview.bin.Cache.log.warn(
2256 "Exception Whilst saving document to " + choice, ex);
2259 removeProgressPanel(progpanel);
2260 if (warnmsg != null)
2262 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2264 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2270 JPanel vamUpdate = null;
2273 * hide vamsas user gui bits when a vamsas document event is being handled.
2276 * true to hide gui, false to reveal gui
2278 public void setVamsasUpdate(boolean b)
2280 Cache.log.debug("Setting gui for Vamsas update "
2281 + (b ? "in progress" : "finished"));
2283 if (vamUpdate != null)
2285 this.removeProgressPanel(vamUpdate);
2289 vamUpdate = this.addProgressPanel(
2290 MessageManager.getString("label.updating_vamsas_session"));
2292 vamsasStart.setVisible(!b);
2293 vamsasStop.setVisible(!b);
2294 vamsasSave.setVisible(!b);
2297 public JInternalFrame[] getAllFrames()
2299 return desktop.getAllFrames();
2303 * Checks the given url to see if it gives a response indicating that the user
2304 * should be informed of a new questionnaire.
2308 public void checkForQuestionnaire(String url)
2310 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2311 // javax.swing.SwingUtilities.invokeLater(jvq);
2312 new Thread(jvq).start();
2315 public void checkURLLinks()
2317 // Thread off the URL link checker
2318 addDialogThread(new Runnable()
2323 if (Cache.getDefault("CHECKURLLINKS", true))
2325 // check what the actual links are - if it's just the default don't
2326 // bother with the warning
2327 List<String> links = Preferences.sequenceUrlLinks
2330 // only need to check links if there is one with a
2331 // SEQUENCE_ID which is not the default EMBL_EBI link
2332 ListIterator<String> li = links.listIterator();
2333 boolean check = false;
2334 List<JLabel> urls = new ArrayList<>();
2335 while (li.hasNext())
2337 String link = li.next();
2338 if (link.contains(SEQUENCE_ID)
2339 && !UrlConstants.isDefaultString(link))
2342 int barPos = link.indexOf("|");
2343 String urlMsg = barPos == -1 ? link
2344 : link.substring(0, barPos) + ": "
2345 + link.substring(barPos + 1);
2346 urls.add(new JLabel(urlMsg));
2354 // ask user to check in case URL links use old style tokens
2355 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2356 JPanel msgPanel = new JPanel();
2357 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2358 msgPanel.add(Box.createVerticalGlue());
2359 JLabel msg = new JLabel(MessageManager
2360 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2361 JLabel msg2 = new JLabel(MessageManager
2362 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2364 for (JLabel url : urls)
2370 final JCheckBox jcb = new JCheckBox(
2371 MessageManager.getString("label.do_not_display_again"));
2372 jcb.addActionListener(new ActionListener()
2375 public void actionPerformed(ActionEvent e)
2377 // update Cache settings for "don't show this again"
2378 boolean showWarningAgain = !jcb.isSelected();
2379 Cache.setProperty("CHECKURLLINKS",
2380 Boolean.valueOf(showWarningAgain).toString());
2385 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2387 .getString("label.SEQUENCE_ID_no_longer_used"),
2388 JvOptionPane.WARNING_MESSAGE);
2395 * Proxy class for JDesktopPane which optionally displays the current memory
2396 * usage and highlights the desktop area with a red bar if free memory runs
2401 public class MyDesktopPane extends JDesktopPane implements Runnable
2404 private static final float ONE_MB = 1048576f;
2406 boolean showMemoryUsage = false;
2410 java.text.NumberFormat df;
2412 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2415 public MyDesktopPane(boolean showMemoryUsage)
2417 showMemoryUsage(showMemoryUsage);
2420 public void showMemoryUsage(boolean showMemory)
2422 this.showMemoryUsage = showMemory;
2425 Thread worker = new Thread(this);
2431 public boolean isShowMemoryUsage()
2433 return showMemoryUsage;
2439 df = java.text.NumberFormat.getNumberInstance();
2440 df.setMaximumFractionDigits(2);
2441 runtime = Runtime.getRuntime();
2443 while (showMemoryUsage)
2447 maxMemory = runtime.maxMemory() / ONE_MB;
2448 allocatedMemory = runtime.totalMemory() / ONE_MB;
2449 freeMemory = runtime.freeMemory() / ONE_MB;
2450 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2452 percentUsage = (totalFreeMemory / maxMemory) * 100;
2454 // if (percentUsage < 20)
2456 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2458 // instance.set.setBorder(border1);
2461 // sleep after showing usage
2463 } catch (Exception ex)
2465 ex.printStackTrace();
2471 public void paintComponent(Graphics g)
2473 if (showMemoryUsage && g != null && df != null)
2475 if (percentUsage < 20)
2477 g.setColor(Color.red);
2479 FontMetrics fm = g.getFontMetrics();
2482 g.drawString(MessageManager.formatMessage("label.memory_stats",
2484 { df.format(totalFreeMemory), df.format(maxMemory),
2485 df.format(percentUsage) }),
2486 10, getHeight() - fm.getHeight());
2494 * Accessor method to quickly get all the AlignmentFrames loaded.
2496 * @return an array of AlignFrame, or null if none found
2498 public static AlignFrame[] getAlignFrames()
2500 if (Jalview.isHeadlessMode())
2502 // Desktop.desktop is null in headless mode
2503 return new AlignFrame[] { Jalview.currentAlignFrame };
2506 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2512 List<AlignFrame> avp = new ArrayList<>();
2514 for (int i = frames.length - 1; i > -1; i--)
2516 if (frames[i] instanceof AlignFrame)
2518 avp.add((AlignFrame) frames[i]);
2520 else if (frames[i] instanceof SplitFrame)
2523 * Also check for a split frame containing an AlignFrame
2525 GSplitFrame sf = (GSplitFrame) frames[i];
2526 if (sf.getTopFrame() instanceof AlignFrame)
2528 avp.add((AlignFrame) sf.getTopFrame());
2530 if (sf.getBottomFrame() instanceof AlignFrame)
2532 avp.add((AlignFrame) sf.getBottomFrame());
2536 if (avp.size() == 0)
2540 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2545 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2549 public GStructureViewer[] getJmols()
2551 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2557 List<GStructureViewer> avp = new ArrayList<>();
2559 for (int i = frames.length - 1; i > -1; i--)
2561 if (frames[i] instanceof AppJmol)
2563 GStructureViewer af = (GStructureViewer) frames[i];
2567 if (avp.size() == 0)
2571 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2576 * Add Groovy Support to Jalview
2579 public void groovyShell_actionPerformed()
2583 openGroovyConsole();
2584 } catch (Exception ex)
2586 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2587 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2589 MessageManager.getString("label.couldnt_create_groovy_shell"),
2590 MessageManager.getString("label.groovy_support_failed"),
2591 JvOptionPane.ERROR_MESSAGE);
2596 * Open the Groovy console
2598 void openGroovyConsole()
2600 if (groovyConsole == null)
2602 groovyConsole = new groovy.ui.Console();
2603 groovyConsole.setVariable("Jalview", this);
2604 groovyConsole.run();
2607 * We allow only one console at a time, so that AlignFrame menu option
2608 * 'Calculate | Run Groovy script' is unambiguous.
2609 * Disable 'Groovy Console', and enable 'Run script', when the console is
2610 * opened, and the reverse when it is closed
2612 Window window = (Window) groovyConsole.getFrame();
2613 window.addWindowListener(new WindowAdapter()
2616 public void windowClosed(WindowEvent e)
2619 * rebind CMD-Q from Groovy Console to Jalview Quit
2622 enableExecuteGroovy(false);
2628 * show Groovy console window (after close and reopen)
2630 ((Window) groovyConsole.getFrame()).setVisible(true);
2633 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2634 * and disable opening a second console
2636 enableExecuteGroovy(true);
2640 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2641 * binding when opened
2643 protected void addQuitHandler()
2645 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
2646 .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
2647 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
2649 getRootPane().getActionMap().put("Quit", new AbstractAction()
2652 public void actionPerformed(ActionEvent e)
2660 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2663 * true if Groovy console is open
2665 public void enableExecuteGroovy(boolean enabled)
2668 * disable opening a second Groovy console
2669 * (or re-enable when the console is closed)
2671 groovyShell.setEnabled(!enabled);
2673 AlignFrame[] alignFrames = getAlignFrames();
2674 if (alignFrames != null)
2676 for (AlignFrame af : alignFrames)
2678 af.setGroovyEnabled(enabled);
2684 * Progress bars managed by the IProgressIndicator method.
2686 private Hashtable<Long, JPanel> progressBars;
2688 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2693 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2696 public void setProgressBar(String message, long id)
2698 if (progressBars == null)
2700 progressBars = new Hashtable<>();
2701 progressBarHandlers = new Hashtable<>();
2704 if (progressBars.get(new Long(id)) != null)
2706 JPanel panel = progressBars.remove(new Long(id));
2707 if (progressBarHandlers.contains(new Long(id)))
2709 progressBarHandlers.remove(new Long(id));
2711 removeProgressPanel(panel);
2715 progressBars.put(new Long(id), addProgressPanel(message));
2722 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2723 * jalview.gui.IProgressIndicatorHandler)
2726 public void registerHandler(final long id,
2727 final IProgressIndicatorHandler handler)
2729 if (progressBarHandlers == null
2730 || !progressBars.containsKey(new Long(id)))
2732 throw new Error(MessageManager.getString(
2733 "error.call_setprogressbar_before_registering_handler"));
2735 progressBarHandlers.put(new Long(id), handler);
2736 final JPanel progressPanel = progressBars.get(new Long(id));
2737 if (handler.canCancel())
2739 JButton cancel = new JButton(
2740 MessageManager.getString("action.cancel"));
2741 final IProgressIndicator us = this;
2742 cancel.addActionListener(new ActionListener()
2746 public void actionPerformed(ActionEvent e)
2748 handler.cancelActivity(id);
2749 us.setProgressBar(MessageManager
2750 .formatMessage("label.cancelled_params", new Object[]
2751 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2755 progressPanel.add(cancel, BorderLayout.EAST);
2761 * @return true if any progress bars are still active
2764 public boolean operationInProgress()
2766 if (progressBars != null && progressBars.size() > 0)
2774 * This will return the first AlignFrame holding the given viewport instance.
2775 * It will break if there are more than one AlignFrames viewing a particular
2779 * @return alignFrame for viewport
2781 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2783 if (desktop != null)
2785 AlignmentPanel[] aps = getAlignmentPanels(
2786 viewport.getSequenceSetId());
2787 for (int panel = 0; aps != null && panel < aps.length; panel++)
2789 if (aps[panel] != null && aps[panel].av == viewport)
2791 return aps[panel].alignFrame;
2798 public VamsasApplication getVamsasApplication()
2805 * flag set if jalview GUI is being operated programmatically
2807 private boolean inBatchMode = false;
2810 * check if jalview GUI is being operated programmatically
2812 * @return inBatchMode
2814 public boolean isInBatchMode()
2820 * set flag if jalview GUI is being operated programmatically
2822 * @param inBatchMode
2824 public void setInBatchMode(boolean inBatchMode)
2826 this.inBatchMode = inBatchMode;
2829 public void startServiceDiscovery()
2831 startServiceDiscovery(false);
2834 public void startServiceDiscovery(boolean blocking)
2836 boolean alive = true;
2837 Thread t0 = null, t1 = null, t2 = null;
2838 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2841 // todo: changesupport handlers need to be transferred
2842 if (discoverer == null)
2844 discoverer = new jalview.ws.jws1.Discoverer();
2845 // register PCS handler for desktop.
2846 discoverer.addPropertyChangeListener(changeSupport);
2848 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2849 // until we phase out completely
2850 (t0 = new Thread(discoverer)).start();
2853 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2855 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2856 .startDiscoverer(changeSupport);
2860 // TODO: do rest service discovery
2869 } catch (Exception e)
2872 alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
2873 || (t3 != null && t3.isAlive())
2874 || (t0 != null && t0.isAlive());
2880 * called to check if the service discovery process completed successfully.
2884 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2886 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2888 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2889 .getErrorMessages();
2892 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2894 if (serviceChangedDialog == null)
2896 // only run if we aren't already displaying one of these.
2897 addDialogThread(serviceChangedDialog = new Runnable()
2904 * JalviewDialog jd =new JalviewDialog() {
2906 * @Override protected void cancelPressed() { // TODO
2907 * Auto-generated method stub
2909 * }@Override protected void okPressed() { // TODO
2910 * Auto-generated method stub
2912 * }@Override protected void raiseClosed() { // TODO
2913 * Auto-generated method stub
2915 * } }; jd.initDialogFrame(new
2916 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2917 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2918 * + " or mis-configured HTTP proxy settings.<br/>" +
2919 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2921 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2922 * ), true, true, "Web Service Configuration Problem", 450,
2925 * jd.waitForInput();
2927 JvOptionPane.showConfirmDialog(Desktop.desktop,
2928 new JLabel("<html><table width=\"450\"><tr><td>"
2929 + ermsg + "</td></tr></table>"
2930 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2931 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2932 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2933 + " Tools->Preferences dialog box to change them.</p></html>"),
2934 "Web Service Configuration Problem",
2935 JvOptionPane.DEFAULT_OPTION,
2936 JvOptionPane.ERROR_MESSAGE);
2937 serviceChangedDialog = null;
2946 "Errors reported by JABA discovery service. Check web services preferences.\n"
2953 private Runnable serviceChangedDialog = null;
2956 * start a thread to open a URL in the configured browser. Pops up a warning
2957 * dialog to the user if there is an exception when calling out to the browser
2962 public static void showUrl(final String url)
2964 showUrl(url, Desktop.instance);
2968 * Like showUrl but allows progress handler to be specified
2972 * (null) or object implementing IProgressIndicator
2974 public static void showUrl(final String url,
2975 final IProgressIndicator progress)
2977 new Thread(new Runnable()
2984 if (progress != null)
2986 progress.setProgressBar(MessageManager
2987 .formatMessage("status.opening_params", new Object[]
2988 { url }), this.hashCode());
2990 jalview.util.BrowserLauncher.openURL(url);
2991 } catch (Exception ex)
2993 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2995 .getString("label.web_browser_not_found_unix"),
2996 MessageManager.getString("label.web_browser_not_found"),
2997 JvOptionPane.WARNING_MESSAGE);
2999 ex.printStackTrace();
3001 if (progress != null)
3003 progress.setProgressBar(null, this.hashCode());
3009 public static WsParamSetManager wsparamManager = null;
3011 public static ParamManager getUserParameterStore()
3013 if (wsparamManager == null)
3015 wsparamManager = new WsParamSetManager();
3017 return wsparamManager;
3021 * static hyperlink handler proxy method for use by Jalview's internal windows
3025 public static void hyperlinkUpdate(HyperlinkEvent e)
3027 if (e.getEventType() == EventType.ACTIVATED)
3032 url = e.getURL().toString();
3033 Desktop.showUrl(url);
3034 } catch (Exception x)
3038 if (Cache.log != null)
3040 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3045 "Couldn't handle string " + url + " as a URL.");
3048 // ignore any exceptions due to dud links.
3055 * single thread that handles display of dialogs to user.
3057 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3060 * flag indicating if dialogExecutor should try to acquire a permit
3062 private volatile boolean dialogPause = true;
3067 private java.util.concurrent.Semaphore block = new Semaphore(0);
3069 private static groovy.ui.Console groovyConsole;
3072 * add another dialog thread to the queue
3076 public void addDialogThread(final Runnable prompter)
3078 dialogExecutor.submit(new Runnable()
3088 } catch (InterruptedException x)
3093 if (instance == null)
3099 SwingUtilities.invokeAndWait(prompter);
3100 } catch (Exception q)
3102 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3108 public void startDialogQueue()
3110 // set the flag so we don't pause waiting for another permit and semaphore
3111 // the current task to begin
3112 dialogPause = false;
3117 protected void snapShotWindow_actionPerformed(ActionEvent e)
3121 ImageMaker im = new jalview.util.ImageMaker(
3122 this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
3123 getHeight(), of = new File("Jalview_snapshot"
3124 + System.currentTimeMillis() + ".eps"),
3125 "View of desktop", null, 0, false);
3128 paintAll(im.getGraphics());
3130 } catch (Exception q)
3132 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3136 Cache.log.info("Successfully written snapshot to file "
3137 + of.getAbsolutePath());
3141 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3142 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3143 * and location last time the view was expanded (if any). However it does not
3144 * remember the split pane divider location - this is set to match the
3145 * 'exploding' frame.
3149 public void explodeViews(SplitFrame sf)
3151 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3152 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3153 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3155 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3157 int viewCount = topPanels.size();
3164 * Processing in reverse order works, forwards order leaves the first panels
3165 * not visible. I don't know why!
3167 for (int i = viewCount - 1; i >= 0; i--)
3170 * Make new top and bottom frames. These take over the respective
3171 * AlignmentPanel objects, including their AlignmentViewports, so the
3172 * cdna/protein relationships between the viewports is carried over to the
3175 * explodedGeometry holds the (x, y) position of the previously exploded
3176 * SplitFrame, and the (width, height) of the AlignFrame component
3178 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3179 AlignFrame newTopFrame = new AlignFrame(topPanel);
3180 newTopFrame.setSize(oldTopFrame.getSize());
3181 newTopFrame.setVisible(true);
3182 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3183 .getExplodedGeometry();
3184 if (geometry != null)
3186 newTopFrame.setSize(geometry.getSize());
3189 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3190 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3191 newBottomFrame.setSize(oldBottomFrame.getSize());
3192 newBottomFrame.setVisible(true);
3193 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3194 .getExplodedGeometry();
3195 if (geometry != null)
3197 newBottomFrame.setSize(geometry.getSize());
3200 topPanel.av.setGatherViewsHere(false);
3201 bottomPanel.av.setGatherViewsHere(false);
3202 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3204 if (geometry != null)
3206 splitFrame.setLocation(geometry.getLocation());
3208 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3212 * Clear references to the panels (now relocated in the new SplitFrames)
3213 * before closing the old SplitFrame.
3216 bottomPanels.clear();
3221 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3222 * back into the given SplitFrame as additional views. Note that the gathered
3223 * frames may themselves have multiple views.
3227 public void gatherViews(GSplitFrame source)
3230 * special handling of explodedGeometry for a view within a SplitFrame: - it
3231 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3232 * height) of the AlignFrame component
3234 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3235 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3236 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3237 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3238 myBottomFrame.viewport
3239 .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
3240 myBottomFrame.getWidth(), myBottomFrame.getHeight()));
3241 myTopFrame.viewport.setGatherViewsHere(true);
3242 myBottomFrame.viewport.setGatherViewsHere(true);
3243 String topViewId = myTopFrame.viewport.getSequenceSetId();
3244 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3246 JInternalFrame[] frames = desktop.getAllFrames();
3247 for (JInternalFrame frame : frames)
3249 if (frame instanceof SplitFrame && frame != source)
3251 SplitFrame sf = (SplitFrame) frame;
3252 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3253 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3254 boolean gatherThis = false;
3255 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3257 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3258 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3259 if (topViewId.equals(topPanel.av.getSequenceSetId())
3260 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3263 topPanel.av.setGatherViewsHere(false);
3264 bottomPanel.av.setGatherViewsHere(false);
3265 topPanel.av.setExplodedGeometry(
3266 new Rectangle(sf.getLocation(), topFrame.getSize()));
3267 bottomPanel.av.setExplodedGeometry(
3268 new Rectangle(sf.getLocation(), bottomFrame.getSize()));
3269 myTopFrame.addAlignmentPanel(topPanel, false);
3270 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3276 topFrame.getAlignPanels().clear();
3277 bottomFrame.getAlignPanels().clear();
3284 * The dust settles...give focus to the tab we did this from.
3286 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3289 public static groovy.ui.Console getGroovyConsole()
3291 return groovyConsole;
3294 public static void transferFromDropTarget(List<String> files,
3295 List<DataSourceType> protocols, DropTargetDropEvent evt,
3296 Transferable t) throws Exception
3299 DataFlavor uriListFlavor = new DataFlavor(
3300 "text/uri-list;class=java.lang.String");
3301 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3303 // Works on Windows and MacOSX
3304 Cache.log.debug("Drop handled as javaFileListFlavor");
3305 for (Object file : (List) t
3306 .getTransferData(DataFlavor.javaFileListFlavor))
3308 files.add(((File) file).toString());
3309 protocols.add(DataSourceType.FILE);
3314 // Unix like behaviour
3315 boolean added = false;
3317 if (t.isDataFlavorSupported(uriListFlavor))
3319 Cache.log.debug("Drop handled as uriListFlavor");
3320 // This is used by Unix drag system
3321 data = (String) t.getTransferData(uriListFlavor);
3325 // fallback to text: workaround - on OSX where there's a JVM bug
3326 Cache.log.debug("standard URIListFlavor failed. Trying text");
3327 // try text fallback
3328 data = (String) t.getTransferData(
3329 new DataFlavor("text/plain;class=java.lang.String"));
3330 if (Cache.log.isDebugEnabled())
3332 Cache.log.debug("fallback returned " + data);
3335 while (protocols.size() < files.size())
3337 Cache.log.debug("Adding missing FILE protocol for "
3338 + files.get(protocols.size()));
3339 protocols.add(DataSourceType.FILE);
3341 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3342 data, "\r\n"); st.hasMoreTokens();)
3345 String s = st.nextToken();
3346 if (s.startsWith("#"))
3348 // the line is a comment (as per the RFC 2483)
3351 java.net.URI uri = new java.net.URI(s);
3352 if (uri.getScheme().toLowerCase().startsWith("http"))
3354 protocols.add(DataSourceType.URL);
3355 files.add(uri.toString());
3359 // otherwise preserve old behaviour: catch all for file objects
3360 java.io.File file = new java.io.File(uri);
3361 protocols.add(DataSourceType.FILE);
3362 files.add(file.toString());
3365 if (Cache.log.isDebugEnabled())
3367 if (data == null || !added)
3370 "Couldn't resolve drop data. Here are the supported flavors:");
3371 for (DataFlavor fl : t.getTransferDataFlavors())
3374 "Supported transfer dataflavor: " + fl.toString());
3375 Object df = t.getTransferData(fl);
3378 Cache.log.debug("Retrieves: " + df);
3382 Cache.log.debug("Retrieved nothing");
3391 * Sets the Preferences property for experimental features to True or False
3392 * depending on the state of the controlling menu item
3395 protected void showExperimental_actionPerformed(boolean selected)
3397 Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
3401 * Answers a (possibly empty) list of any structure viewer frames (currently
3402 * for either Jmol or Chimera) which are currently open. This may optionally
3403 * be restricted to viewers of a specified class, or viewers linked to a
3404 * specified alignment panel.
3407 * if not null, only return viewers linked to this panel
3408 * @param structureViewerClass
3409 * if not null, only return viewers of this class
3412 public List<StructureViewerBase> getStructureViewers(
3413 AlignmentPanel apanel,
3414 Class<? extends StructureViewerBase> structureViewerClass)
3416 List<StructureViewerBase> result = new ArrayList<>();
3417 JInternalFrame[] frames = Desktop.instance.getAllFrames();
3419 for (JInternalFrame frame : frames)
3421 if (frame instanceof StructureViewerBase)
3423 if (structureViewerClass == null
3424 || structureViewerClass.isInstance(frame))
3427 || ((StructureViewerBase) frame).isLinkedWith(apanel))
3429 result.add((StructureViewerBase) frame);