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.EMBLEBI_STRING;
24 import static jalview.util.UrlConstants.SEQUENCE_ID;
26 import jalview.api.AlignViewportI;
27 import jalview.api.AlignmentViewPanel;
28 import jalview.bin.Cache;
29 import jalview.bin.Jalview;
30 import jalview.io.DataSourceType;
31 import jalview.io.FileFormat;
32 import jalview.io.FileFormatException;
33 import jalview.io.FileFormatI;
34 import jalview.io.FileFormats;
35 import jalview.io.FileLoader;
36 import jalview.io.IdentifyFile;
37 import jalview.io.JalviewFileChooser;
38 import jalview.io.JalviewFileView;
39 import jalview.jbgui.GSplitFrame;
40 import jalview.jbgui.GStructureViewer;
41 import jalview.structure.StructureSelectionManager;
42 import jalview.util.ImageMaker;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.viewmodel.AlignmentViewport;
46 import jalview.ws.params.ParamManager;
48 import java.awt.BorderLayout;
49 import java.awt.Color;
50 import java.awt.Dimension;
51 import java.awt.FontMetrics;
52 import java.awt.Graphics;
53 import java.awt.GridLayout;
54 import java.awt.Point;
55 import java.awt.Rectangle;
56 import java.awt.Toolkit;
57 import java.awt.Window;
58 import java.awt.datatransfer.Clipboard;
59 import java.awt.datatransfer.ClipboardOwner;
60 import java.awt.datatransfer.DataFlavor;
61 import java.awt.datatransfer.Transferable;
62 import java.awt.dnd.DnDConstants;
63 import java.awt.dnd.DropTargetDragEvent;
64 import java.awt.dnd.DropTargetDropEvent;
65 import java.awt.dnd.DropTargetEvent;
66 import java.awt.dnd.DropTargetListener;
67 import java.awt.event.ActionEvent;
68 import java.awt.event.ActionListener;
69 import java.awt.event.FocusEvent;
70 import java.awt.event.FocusListener;
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;
82 import java.util.ArrayList;
83 import java.util.Hashtable;
84 import java.util.List;
85 import java.util.ListIterator;
86 import java.util.StringTokenizer;
87 import java.util.Vector;
88 import java.util.concurrent.ExecutorService;
89 import java.util.concurrent.Executors;
90 import java.util.concurrent.Semaphore;
92 import javax.swing.AbstractAction;
93 import javax.swing.Box;
94 import javax.swing.BoxLayout;
95 import javax.swing.DefaultDesktopManager;
96 import javax.swing.DesktopManager;
97 import javax.swing.JButton;
98 import javax.swing.JCheckBox;
99 import javax.swing.JComboBox;
100 import javax.swing.JComponent;
101 import javax.swing.JDesktopPane;
102 import javax.swing.JFrame;
103 import javax.swing.JInternalFrame;
104 import javax.swing.JLabel;
105 import javax.swing.JMenuItem;
106 import javax.swing.JPanel;
107 import javax.swing.JPopupMenu;
108 import javax.swing.JProgressBar;
109 import javax.swing.KeyStroke;
110 import javax.swing.SwingUtilities;
111 import javax.swing.event.HyperlinkEvent;
112 import javax.swing.event.HyperlinkEvent.EventType;
113 import javax.swing.event.InternalFrameAdapter;
114 import javax.swing.event.InternalFrameEvent;
115 import javax.swing.event.MenuEvent;
116 import javax.swing.event.MenuListener;
123 * @version $Revision: 1.155 $
125 public class Desktop extends jalview.jbgui.GDesktop implements
126 DropTargetListener, ClipboardOwner, IProgressIndicator,
127 jalview.api.StructureSelectionManagerProvider
130 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
133 * news reader - null if it was never started.
135 private BlogReader jvnews = null;
137 private File projectFile;
141 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
143 public void addJalviewPropertyChangeListener(
144 PropertyChangeListener listener)
146 changeSupport.addJalviewPropertyChangeListener(listener);
150 * @param propertyName
152 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
153 * java.beans.PropertyChangeListener)
155 public void addJalviewPropertyChangeListener(String propertyName,
156 PropertyChangeListener listener)
158 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
162 * @param propertyName
164 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
165 * java.beans.PropertyChangeListener)
167 public void removeJalviewPropertyChangeListener(String propertyName,
168 PropertyChangeListener listener)
170 changeSupport.removeJalviewPropertyChangeListener(propertyName,
174 /** Singleton Desktop instance */
175 public static Desktop instance;
177 public static MyDesktopPane desktop;
179 static int openFrameCount = 0;
181 static final int xOffset = 30;
183 static final int yOffset = 30;
185 public static jalview.ws.jws1.Discoverer discoverer;
187 public static Object[] jalviewClipboard;
189 public static boolean internalCopy = false;
191 static int fileLoadingCount = 0;
193 class MyDesktopManager implements DesktopManager
196 private DesktopManager delegate;
198 public MyDesktopManager(DesktopManager delegate)
200 this.delegate = delegate;
204 public void activateFrame(JInternalFrame f)
208 delegate.activateFrame(f);
209 } catch (NullPointerException npe)
211 Point p = getMousePosition();
212 instance.showPasteMenu(p.x, p.y);
217 public void beginDraggingFrame(JComponent f)
219 delegate.beginDraggingFrame(f);
223 public void beginResizingFrame(JComponent f, int direction)
225 delegate.beginResizingFrame(f, direction);
229 public void closeFrame(JInternalFrame f)
231 delegate.closeFrame(f);
235 public void deactivateFrame(JInternalFrame f)
237 delegate.deactivateFrame(f);
241 public void deiconifyFrame(JInternalFrame f)
243 delegate.deiconifyFrame(f);
247 public void dragFrame(JComponent f, int newX, int newY)
253 delegate.dragFrame(f, newX, newY);
257 public void endDraggingFrame(JComponent f)
259 delegate.endDraggingFrame(f);
263 public void endResizingFrame(JComponent f)
265 delegate.endResizingFrame(f);
269 public void iconifyFrame(JInternalFrame f)
271 delegate.iconifyFrame(f);
275 public void maximizeFrame(JInternalFrame f)
277 delegate.maximizeFrame(f);
281 public void minimizeFrame(JInternalFrame f)
283 delegate.minimizeFrame(f);
287 public void openFrame(JInternalFrame f)
289 delegate.openFrame(f);
293 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
300 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
304 public void setBoundsForFrame(JComponent f, int newX, int newY,
305 int newWidth, int newHeight)
307 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
310 // All other methods, simply delegate
315 * Creates a new Desktop object.
320 * A note to implementors. It is ESSENTIAL that any activities that might
321 * block are spawned off as threads rather than waited for during this
325 doVamsasClientCheck();
327 groovyShell = new JMenuItem();
328 groovyShell.setText(MessageManager.getString("label.groovy_console"));
329 groovyShell.addActionListener(new ActionListener()
332 public void actionPerformed(ActionEvent e)
334 groovyShell_actionPerformed();
337 toolsMenu.add(groovyShell);
338 groovyShell.setVisible(true);
340 doConfigureStructurePrefs();
341 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
342 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
345 boolean showjconsole = jalview.bin.Cache.getDefault(
346 "SHOW_JAVA_CONSOLE", false);
347 desktop = new MyDesktopPane(selmemusage);
348 if (Platform.isAMac())
350 desktop.setDoubleBuffered(false);
352 showMemusage.setSelected(selmemusage);
353 desktop.setBackground(Color.white);
354 getContentPane().setLayout(new BorderLayout());
355 // alternate config - have scrollbars - see notes in JAL-153
356 // JScrollPane sp = new JScrollPane();
357 // sp.getViewport().setView(desktop);
358 // getContentPane().add(sp, BorderLayout.CENTER);
359 getContentPane().add(desktop, BorderLayout.CENTER);
360 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
362 // This line prevents Windows Look&Feel resizing all new windows to maximum
363 // if previous window was maximised
364 desktop.setDesktopManager(new MyDesktopManager(
365 new DefaultDesktopManager()));
367 Rectangle dims = getLastKnownDimensions("");
374 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
375 setBounds((screenSize.width - 900) / 2,
376 (screenSize.height - 650) / 2, 900, 650);
378 jconsole = new Console(this, showjconsole);
379 // add essential build information
380 jconsole.setHeader("Jalview Version: "
381 + jalview.bin.Cache.getProperty("VERSION") + "\n"
382 + "Jalview Installation: "
383 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
384 + "\n" + "Build Date: "
385 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
386 + "Java version: " + System.getProperty("java.version") + "\n"
387 + System.getProperty("os.arch") + " "
388 + System.getProperty("os.name") + " "
389 + System.getProperty("os.version"));
391 showConsole(showjconsole);
393 showNews.setVisible(false);
397 this.addWindowListener(new WindowAdapter()
400 public void windowClosing(WindowEvent evt)
407 this.addMouseListener(ma = new MouseAdapter()
410 public void mousePressed(MouseEvent evt)
412 if (evt.isPopupTrigger()) // Mac
414 showPasteMenu(evt.getX(), evt.getY());
419 public void mouseReleased(MouseEvent evt)
421 if (evt.isPopupTrigger()) // Windows
423 showPasteMenu(evt.getX(), evt.getY());
427 desktop.addMouseListener(ma);
429 this.addFocusListener(new FocusListener()
433 public void focusLost(FocusEvent e)
435 // TODO Auto-generated method stub
440 public void focusGained(FocusEvent e)
442 Cache.log.debug("Relaying windows after focus gain");
443 // make sure that we sort windows properly after we gain focus
444 instance.relayerWindows();
447 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
448 // Spawn a thread that shows the splashscreen
449 SwingUtilities.invokeLater(new Runnable()
458 // Thread off a new instance of the file chooser - this reduces the time it
459 // takes to open it later on.
460 new Thread(new Runnable()
465 Cache.log.debug("Filechooser init thread started.");
466 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
467 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
469 Cache.log.debug("Filechooser init thread finished.");
472 // Add the service change listener
473 changeSupport.addJalviewPropertyChangeListener("services",
474 new PropertyChangeListener()
478 public void propertyChange(PropertyChangeEvent evt)
480 Cache.log.debug("Firing service changed event for "
481 + evt.getNewValue());
482 JalviewServicesChanged(evt);
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.getDefault(
496 Preferences.ADD_TEMPFACT_ANN, true));
497 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
498 Preferences.STRUCT_FROM_PDB, true));
499 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
500 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.");
529 protected void showNews_actionPerformed(ActionEvent e)
531 showNews(showNews.isSelected());
534 void showNews(boolean visible)
537 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
538 showNews.setSelected(visible);
539 if (visible && !jvnews.isVisible())
541 new Thread(new Runnable()
546 long now = System.currentTimeMillis();
547 Desktop.instance.setProgressBar(
548 MessageManager.getString("status.refreshing_news"), now);
549 jvnews.refreshNews();
550 Desktop.instance.setProgressBar(null, now);
559 * recover the last known dimensions for a jalview window
562 * - empty string is desktop, all other windows have unique prefix
563 * @return null or last known dimensions scaled to current geometry (if last
564 * window geom was known)
566 Rectangle getLastKnownDimensions(String windowName)
568 // TODO: lock aspect ratio for scaling desktop Bug #0058199
569 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
570 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
571 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
572 String width = jalview.bin.Cache.getProperty(windowName
574 String height = jalview.bin.Cache.getProperty(windowName
576 if ((x != null) && (y != null) && (width != null) && (height != null))
578 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
579 .parseInt(width), ih = Integer.parseInt(height);
580 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
582 // attempt #1 - try to cope with change in screen geometry - this
583 // version doesn't preserve original jv aspect ratio.
584 // take ratio of current screen size vs original screen size.
585 double sw = ((1f * screenSize.width) / (1f * Integer
586 .parseInt(jalview.bin.Cache
587 .getProperty("SCREENGEOMETRY_WIDTH"))));
588 double sh = ((1f * screenSize.height) / (1f * Integer
589 .parseInt(jalview.bin.Cache
590 .getProperty("SCREENGEOMETRY_HEIGHT"))));
591 // rescale the bounds depending upon the current screen geometry.
592 ix = (int) (ix * sw);
593 iw = (int) (iw * sw);
594 iy = (int) (iy * sh);
595 ih = (int) (ih * sh);
596 while (ix >= screenSize.width)
598 jalview.bin.Cache.log
599 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
600 ix -= screenSize.width;
602 while (iy >= screenSize.height)
604 jalview.bin.Cache.log
605 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
606 iy -= screenSize.height;
608 jalview.bin.Cache.log.debug("Got last known dimensions for "
609 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
612 // return dimensions for new instance
613 return new Rectangle(ix, iy, iw, ih);
618 private void doVamsasClientCheck()
620 if (jalview.bin.Cache.vamsasJarsPresent())
622 setupVamsasDisconnectedGui();
623 VamsasMenu.setVisible(true);
624 final Desktop us = this;
625 VamsasMenu.addMenuListener(new MenuListener()
627 // this listener remembers when the menu was first selected, and
628 // doesn't rebuild the session list until it has been cleared and
630 boolean refresh = true;
633 public void menuCanceled(MenuEvent e)
639 public void menuDeselected(MenuEvent e)
645 public void menuSelected(MenuEvent e)
649 us.buildVamsasStMenu();
654 vamsasStart.setVisible(true);
658 void showPasteMenu(int x, int y)
660 JPopupMenu popup = new JPopupMenu();
661 JMenuItem item = new JMenuItem(
662 MessageManager.getString("label.paste_new_window"));
663 item.addActionListener(new ActionListener()
666 public void actionPerformed(ActionEvent evt)
673 popup.show(this, x, y);
680 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
681 Transferable contents = c.getContents(this);
683 if (contents != null)
685 String file = (String) contents
686 .getTransferData(DataFlavor.stringFlavor);
688 FileFormatI format = new IdentifyFile().identify(file,
689 DataSourceType.PASTE);
691 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
694 } catch (Exception ex)
697 .println("Unable to paste alignment from system clipboard:\n"
703 * Adds and opens the given frame to the desktop
714 public static synchronized void addInternalFrame(
715 final JInternalFrame frame, String title, int w, int h)
717 addInternalFrame(frame, title, true, w, h, true);
721 * Add an internal frame to the Jalview desktop
728 * When true, display frame immediately, otherwise, caller must call
729 * setVisible themselves.
735 public static synchronized void addInternalFrame(
736 final JInternalFrame frame, String title, boolean makeVisible,
739 addInternalFrame(frame, title, makeVisible, w, h, true);
743 * Add an internal frame to the Jalview desktop and make it visible
756 public static synchronized void addInternalFrame(
757 final JInternalFrame frame, String title, int w, int h,
760 addInternalFrame(frame, title, true, w, h, resizable);
764 * Add an internal frame to the Jalview desktop
771 * When true, display frame immediately, otherwise, caller must call
772 * setVisible themselves.
780 public static synchronized void addInternalFrame(
781 final JInternalFrame frame, String title, boolean makeVisible,
782 int w, int h, boolean resizable)
785 // TODO: allow callers to determine X and Y position of frame (eg. via
787 // TODO: consider fixing method to update entries in the window submenu with
788 // the current window title
790 frame.setTitle(title);
791 if (frame.getWidth() < 1 || frame.getHeight() < 1)
795 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
796 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
797 // IF JALVIEW IS RUNNING HEADLESS
798 // ///////////////////////////////////////////////
800 || (System.getProperty("java.awt.headless") != null && System
801 .getProperty("java.awt.headless").equals("true")))
808 frame.setVisible(makeVisible);
809 frame.setClosable(true);
810 frame.setResizable(resizable);
811 frame.setMaximizable(resizable);
812 frame.setIconifiable(resizable);
813 if (Platform.isAMac())
815 frame.setIconifiable(false);
816 frame.setFrameIcon(null);
817 // frame.setDesktopIcon(null);
818 frame.setDoubleBuffered(false);
820 if (frame.getX() < 1 && frame.getY() < 1)
822 frame.setLocation(xOffset * openFrameCount, yOffset
823 * ((openFrameCount - 1) % 10) + yOffset);
827 * add an entry for the new frame in the Window menu
828 * (and remove it when the frame is closed)
830 final JMenuItem menuItem = new JMenuItem(title);
831 frame.addInternalFrameListener(new InternalFrameAdapter()
834 public void internalFrameActivated(InternalFrameEvent evt)
836 JInternalFrame itf = desktop.getSelectedFrame();
844 public void internalFrameClosed(InternalFrameEvent evt)
846 PaintRefresher.RemoveComponent(frame);
849 * defensive check to prevent frames being
850 * added half off the window
852 if (openFrameCount > 0)
858 * ensure no reference to alignFrame retained by menu item listener
860 if (menuItem.getActionListeners().length > 0)
862 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
864 windowMenu.remove(menuItem);
865 JInternalFrame itf = desktop.getSelectedFrame();
869 if (itf instanceof AlignFrame)
871 Jalview.setCurrentAlignFrame((AlignFrame) itf);
878 menuItem.addActionListener(new ActionListener()
881 public void actionPerformed(ActionEvent e)
885 frame.setSelected(true);
886 frame.setIcon(false);
887 } catch (java.beans.PropertyVetoException ex)
896 windowMenu.add(menuItem);
901 frame.setSelected(true);
902 frame.requestFocus();
903 } catch (java.beans.PropertyVetoException ve)
905 } catch (java.lang.ClassCastException cex)
908 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
914 public void lostOwnership(Clipboard clipboard, Transferable contents)
918 Desktop.jalviewClipboard = null;
921 internalCopy = false;
925 public void dragEnter(DropTargetDragEvent evt)
930 public void dragExit(DropTargetEvent evt)
935 public void dragOver(DropTargetDragEvent evt)
940 public void dropActionChanged(DropTargetDragEvent evt)
951 public void drop(DropTargetDropEvent evt)
953 boolean success = true;
954 // JAL-1552 - acceptDrop required before getTransferable call for
955 // Java's Transferable for native dnd
956 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
957 Transferable t = evt.getTransferable();
958 List<String> files = new ArrayList<String>();
959 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
963 Desktop.transferFromDropTarget(files, protocols, evt, t);
964 } catch (Exception e)
974 for (int i = 0; i < files.size(); i++)
976 String file = files.get(i).toString();
977 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
979 FileFormatI format = null;
981 if (file.endsWith(".jar"))
983 format = FileFormat.Jalview;
988 format = new IdentifyFile().identify(file, protocol);
991 new FileLoader().LoadFile(file, protocol, format);
994 } catch (Exception ex)
999 evt.dropComplete(success); // need this to ensure input focus is properly
1000 // transfered to any new windows created
1010 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1012 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1013 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1014 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1016 chooser.setFileView(new JalviewFileView());
1017 chooser.setDialogTitle(MessageManager
1018 .getString("label.open_local_file"));
1019 chooser.setToolTipText(MessageManager.getString("action.open"));
1021 int value = chooser.showOpenDialog(this);
1023 if (value == JalviewFileChooser.APPROVE_OPTION)
1025 String choice = chooser.getSelectedFile().getPath();
1026 Cache.setProperty("LAST_DIRECTORY", chooser
1027 .getSelectedFile().getParent());
1029 FileFormatI format = chooser.getSelectedFormat();
1032 * Call IdentifyFile to verify the file contains what its extension implies.
1033 * Skip this step for dynamically added file formats, because
1034 * IdentifyFile does not know how to recognise them.
1036 if (FileFormats.getInstance().isIdentifiable(format))
1040 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1041 } catch (FileFormatException e)
1043 // format = null; //??
1047 if (viewport != null)
1049 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1054 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1066 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1068 // This construct allows us to have a wider textfield
1070 JLabel label = new JLabel(
1071 MessageManager.getString("label.input_file_url"));
1072 final JComboBox history = new JComboBox();
1074 JPanel panel = new JPanel(new GridLayout(2, 1));
1077 history.setPreferredSize(new Dimension(400, 20));
1078 history.setEditable(true);
1079 history.addItem("http://www.");
1081 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1085 if (historyItems != null)
1087 st = new StringTokenizer(historyItems, "\t");
1089 while (st.hasMoreTokens())
1091 history.addItem(st.nextElement());
1095 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1096 MessageManager.getString("label.input_alignment_from_url"),
1097 JvOptionPane.OK_CANCEL_OPTION);
1099 if (reply != JvOptionPane.OK_OPTION)
1104 String url = history.getSelectedItem().toString();
1106 if (url.toLowerCase().endsWith(".jar"))
1108 if (viewport != null)
1110 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1111 FileFormat.Jalview);
1115 new FileLoader().LoadFile(url, DataSourceType.URL,
1116 FileFormat.Jalview);
1121 FileFormatI format = null;
1124 format = new IdentifyFile().identify(url, DataSourceType.URL);
1125 } catch (FileFormatException e)
1127 // TODO revise error handling, distinguish between
1128 // URL not found and response not valid
1133 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1134 MessageManager.formatMessage("label.couldnt_locate",
1135 new Object[] { url }), MessageManager
1136 .getString("label.url_not_found"),
1137 JvOptionPane.WARNING_MESSAGE);
1142 if (viewport != null)
1145 .LoadFile(viewport, url, DataSourceType.URL, format);
1149 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1155 * Opens the CutAndPaste window for the user to paste an alignment in to
1158 * - if not null, the pasted alignment is added to the current
1159 * alignment; if null, to a new alignment window
1162 public void inputTextboxMenuItem_actionPerformed(
1163 AlignmentViewPanel viewPanel)
1165 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1166 cap.setForInput(viewPanel);
1167 Desktop.addInternalFrame(cap,
1168 MessageManager.getString("label.cut_paste_alignmen_file"),
1178 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1180 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1181 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1183 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1184 getBounds().y, getWidth(), getHeight()));
1186 if (jconsole != null)
1188 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1189 jconsole.stopConsole();
1193 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1196 if (dialogExecutor != null)
1198 dialogExecutor.shutdownNow();
1200 closeAll_actionPerformed(null);
1202 if (groovyConsole != null)
1204 // suppress a possible repeat prompt to save script
1205 groovyConsole.setDirty(false);
1206 groovyConsole.exit();
1211 private void storeLastKnownDimensions(String string, Rectangle jc)
1213 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1214 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1215 + " height:" + jc.height);
1217 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1218 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1219 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1220 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1230 public void aboutMenuItem_actionPerformed(ActionEvent e)
1232 // StringBuffer message = getAboutMessage(false);
1233 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1235 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1236 new Thread(new Runnable()
1241 new SplashScreen(true);
1246 public StringBuffer getAboutMessage(boolean shortv)
1248 StringBuffer message = new StringBuffer();
1249 message.append("<html>");
1252 message.append("<h1><strong>Version: "
1253 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1254 message.append("<strong>Last Updated: <em>"
1255 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1256 + "</em></strong>");
1262 message.append("<strong>Version "
1263 + jalview.bin.Cache.getProperty("VERSION")
1264 + "; last updated: "
1265 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1268 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1271 message.append("<br>...Checking latest version...</br>");
1273 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1274 .equals(jalview.bin.Cache.getProperty("VERSION")))
1276 boolean red = false;
1277 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1278 .indexOf("automated build") == -1)
1281 // Displayed when code version and jnlp version do not match and code
1282 // version is not a development build
1283 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1286 message.append("<br>!! Version "
1287 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1289 + " is available for download from "
1290 + jalview.bin.Cache.getDefault("www.jalview.org",
1291 "http://www.jalview.org") + " !!");
1294 message.append("</div>");
1297 message.append("<br>Authors: "
1299 .getDefault("AUTHORFNAMES",
1300 "The Jalview Authors (See AUTHORS file for current list)")
1301 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1302 + "<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"
1303 + "<br><br>If you use Jalview, please cite:"
1304 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1305 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1306 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1318 public void documentationMenuItem_actionPerformed(ActionEvent e)
1322 Help.showHelpWindow();
1323 } catch (Exception ex)
1329 public void closeAll_actionPerformed(ActionEvent e)
1331 // TODO show a progress bar while closing?
1332 JInternalFrame[] frames = desktop.getAllFrames();
1333 for (int i = 0; i < frames.length; i++)
1337 frames[i].setClosed(true);
1338 } catch (java.beans.PropertyVetoException ex)
1342 Jalview.setCurrentAlignFrame(null);
1343 System.out.println("ALL CLOSED");
1344 if (v_client != null)
1346 // TODO clear binding to vamsas document objects on close_all
1350 * reset state of singleton objects as appropriate (clear down session state
1351 * when all windows are closed)
1353 StructureSelectionManager ssm = StructureSelectionManager
1354 .getStructureSelectionManager(this);
1363 public void raiseRelated_actionPerformed(ActionEvent e)
1365 reorderAssociatedWindows(false, false);
1369 public void minimizeAssociated_actionPerformed(ActionEvent e)
1371 reorderAssociatedWindows(true, false);
1374 void closeAssociatedWindows()
1376 reorderAssociatedWindows(false, true);
1382 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1386 protected void garbageCollect_actionPerformed(ActionEvent e)
1388 // We simply collect the garbage
1389 jalview.bin.Cache.log.debug("Collecting garbage...");
1391 jalview.bin.Cache.log.debug("Finished garbage collection.");
1398 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1402 protected void showMemusage_actionPerformed(ActionEvent e)
1404 desktop.showMemoryUsage(showMemusage.isSelected());
1411 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1415 protected void showConsole_actionPerformed(ActionEvent e)
1417 showConsole(showConsole.isSelected());
1420 Console jconsole = null;
1423 * control whether the java console is visible or not
1427 void showConsole(boolean selected)
1429 showConsole.setSelected(selected);
1430 // TODO: decide if we should update properties file
1431 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1433 jconsole.setVisible(selected);
1436 void reorderAssociatedWindows(boolean minimize, boolean close)
1438 JInternalFrame[] frames = desktop.getAllFrames();
1439 if (frames == null || frames.length < 1)
1444 AlignmentViewport source = null, target = null;
1445 if (frames[0] instanceof AlignFrame)
1447 source = ((AlignFrame) frames[0]).getCurrentView();
1449 else if (frames[0] instanceof TreePanel)
1451 source = ((TreePanel) frames[0]).getViewPort();
1453 else if (frames[0] instanceof PCAPanel)
1455 source = ((PCAPanel) frames[0]).av;
1457 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1459 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1464 for (int i = 0; i < frames.length; i++)
1467 if (frames[i] == null)
1471 if (frames[i] instanceof AlignFrame)
1473 target = ((AlignFrame) frames[i]).getCurrentView();
1475 else if (frames[i] instanceof TreePanel)
1477 target = ((TreePanel) frames[i]).getViewPort();
1479 else if (frames[i] instanceof PCAPanel)
1481 target = ((PCAPanel) frames[i]).av;
1483 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1485 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1488 if (source == target)
1494 frames[i].setClosed(true);
1498 frames[i].setIcon(minimize);
1501 frames[i].toFront();
1505 } catch (java.beans.PropertyVetoException ex)
1520 protected void preferences_actionPerformed(ActionEvent e)
1532 public void saveState_actionPerformed(ActionEvent e)
1534 JalviewFileChooser chooser = new JalviewFileChooser("jvp",
1537 chooser.setFileView(new JalviewFileView());
1538 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1540 int value = chooser.showSaveDialog(this);
1542 if (value == JalviewFileChooser.APPROVE_OPTION)
1544 final Desktop me = this;
1545 final java.io.File choice = chooser.getSelectedFile();
1546 setProjectFile(choice);
1548 new Thread(new Runnable()
1553 // TODO: refactor to Jalview desktop session controller action.
1554 setProgressBar(MessageManager.formatMessage(
1555 "label.saving_jalview_project",
1556 new Object[] { choice.getName() }), choice.hashCode());
1557 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1558 choice.getParent());
1559 // TODO catch and handle errors for savestate
1560 // TODO prevent user from messing with the Desktop whilst we're saving
1563 new Jalview2XML().saveState(choice);
1564 } catch (OutOfMemoryError oom)
1566 new OOMWarning("Whilst saving current state to "
1567 + choice.getName(), oom);
1568 } catch (Exception ex)
1571 "Problems whilst trying to save to " + choice.getName(),
1573 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1574 "label.error_whilst_saving_current_state_to",
1575 new Object[] { choice.getName() }), MessageManager
1576 .getString("label.couldnt_save_project"),
1577 JvOptionPane.WARNING_MESSAGE);
1579 setProgressBar(null, choice.hashCode());
1585 private void setProjectFile(File choice)
1587 this.projectFile = choice;
1590 public File getProjectFile()
1592 return this.projectFile;
1602 public void loadState_actionPerformed(ActionEvent e)
1604 JalviewFileChooser chooser = new JalviewFileChooser(
1605 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1606 "jvp", "jar" }, new String[] { "Jalview Project",
1607 "Jalview Project (old)" }, "Jalview Project");
1608 chooser.setFileView(new JalviewFileView());
1609 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1611 int value = chooser.showOpenDialog(this);
1613 if (value == JalviewFileChooser.APPROVE_OPTION)
1615 final File selectedFile = chooser.getSelectedFile();
1616 setProjectFile(selectedFile);
1617 final String choice = selectedFile.getAbsolutePath();
1618 Cache.setProperty("LAST_DIRECTORY",
1619 selectedFile.getParent());
1620 new Thread(new Runnable()
1626 MessageManager.formatMessage(
1627 "label.loading_jalview_project",
1628 new Object[] { choice }), choice.hashCode());
1631 new Jalview2XML().loadJalviewAlign(choice);
1632 } catch (OutOfMemoryError oom)
1634 new OOMWarning("Whilst loading project from " + choice, oom);
1635 } catch (Exception ex)
1637 Cache.log.error("Problems whilst loading project from "
1639 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1641 "label.error_whilst_loading_project_from",
1642 new Object[] { choice }), MessageManager
1643 .getString("label.couldnt_load_project"),
1644 JvOptionPane.WARNING_MESSAGE);
1646 setProgressBar(null, choice.hashCode());
1653 public void inputSequence_actionPerformed(ActionEvent e)
1655 new SequenceFetcher(this);
1658 JPanel progressPanel;
1660 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1662 public void startLoading(final String fileName)
1664 if (fileLoadingCount == 0)
1666 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1667 "label.loading_file", new Object[] { fileName })));
1672 private JPanel addProgressPanel(String string)
1674 if (progressPanel == null)
1676 progressPanel = new JPanel(new GridLayout(1, 1));
1677 totalProgressCount = 0;
1678 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1680 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1681 JProgressBar progressBar = new JProgressBar();
1682 progressBar.setIndeterminate(true);
1684 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1686 thisprogress.add(progressBar, BorderLayout.CENTER);
1687 progressPanel.add(thisprogress);
1688 ((GridLayout) progressPanel.getLayout())
1689 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1690 ++totalProgressCount;
1691 instance.validate();
1692 return thisprogress;
1695 int totalProgressCount = 0;
1697 private void removeProgressPanel(JPanel progbar)
1699 if (progressPanel != null)
1701 synchronized (progressPanel)
1703 progressPanel.remove(progbar);
1704 GridLayout gl = (GridLayout) progressPanel.getLayout();
1705 gl.setRows(gl.getRows() - 1);
1706 if (--totalProgressCount < 1)
1708 this.getContentPane().remove(progressPanel);
1709 progressPanel = null;
1716 public void stopLoading()
1719 if (fileLoadingCount < 1)
1721 while (fileLoadingPanels.size() > 0)
1723 removeProgressPanel(fileLoadingPanels.remove(0));
1725 fileLoadingPanels.clear();
1726 fileLoadingCount = 0;
1731 public static int getViewCount(String alignmentId)
1733 AlignmentViewport[] aps = getViewports(alignmentId);
1734 return (aps == null) ? 0 : aps.length;
1739 * @param alignmentId
1740 * - if null, all sets are returned
1741 * @return all AlignmentPanels concerning the alignmentId sequence set
1743 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1745 if (Desktop.desktop == null)
1747 // no frames created and in headless mode
1748 // TODO: verify that frames are recoverable when in headless mode
1751 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1752 AlignFrame[] frames = getAlignFrames();
1757 for (AlignFrame af : frames)
1759 for (AlignmentPanel ap : af.alignPanels)
1761 if (alignmentId == null
1762 || alignmentId.equals(ap.av.getSequenceSetId()))
1768 if (aps.size() == 0)
1772 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1777 * get all the viewports on an alignment.
1779 * @param sequenceSetId
1780 * unique alignment id (may be null - all viewports returned in that
1782 * @return all viewports on the alignment bound to sequenceSetId
1784 public static AlignmentViewport[] getViewports(String sequenceSetId)
1786 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1787 if (desktop != null)
1789 AlignFrame[] frames = Desktop.getAlignFrames();
1791 for (AlignFrame afr : frames)
1793 if (sequenceSetId == null
1794 || afr.getViewport().getSequenceSetId()
1795 .equals(sequenceSetId))
1797 if (afr.alignPanels != null)
1799 for (AlignmentPanel ap : afr.alignPanels)
1801 if (sequenceSetId == null
1802 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1810 viewp.add(afr.getViewport());
1814 if (viewp.size() > 0)
1816 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1823 * Explode the views in the given frame into separate AlignFrame
1827 public static void explodeViews(AlignFrame af)
1829 int size = af.alignPanels.size();
1835 for (int i = 0; i < size; i++)
1837 AlignmentPanel ap = af.alignPanels.get(i);
1838 AlignFrame newaf = new AlignFrame(ap);
1841 * Restore the view's last exploded frame geometry if known. Multiple
1842 * views from one exploded frame share and restore the same (frame)
1843 * position and size.
1845 Rectangle geometry = ap.av.getExplodedGeometry();
1846 if (geometry != null)
1848 newaf.setBounds(geometry);
1851 ap.av.setGatherViewsHere(false);
1853 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1854 AlignFrame.DEFAULT_HEIGHT);
1857 af.alignPanels.clear();
1858 af.closeMenuItem_actionPerformed(true);
1863 * Gather expanded views (separate AlignFrame's) with the same sequence set
1864 * identifier back in to this frame as additional views, and close the
1865 * expanded views. Note the expanded frames may themselves have multiple
1866 * views. We take the lot.
1870 public void gatherViews(AlignFrame source)
1872 source.viewport.setGatherViewsHere(true);
1873 source.viewport.setExplodedGeometry(source.getBounds());
1874 JInternalFrame[] frames = desktop.getAllFrames();
1875 String viewId = source.viewport.getSequenceSetId();
1877 for (int t = 0; t < frames.length; t++)
1879 if (frames[t] instanceof AlignFrame && frames[t] != source)
1881 AlignFrame af = (AlignFrame) frames[t];
1882 boolean gatherThis = false;
1883 for (int a = 0; a < af.alignPanels.size(); a++)
1885 AlignmentPanel ap = af.alignPanels.get(a);
1886 if (viewId.equals(ap.av.getSequenceSetId()))
1889 ap.av.setGatherViewsHere(false);
1890 ap.av.setExplodedGeometry(af.getBounds());
1891 source.addAlignmentPanel(ap, false);
1897 af.alignPanels.clear();
1898 af.closeMenuItem_actionPerformed(true);
1905 jalview.gui.VamsasApplication v_client = null;
1908 public void vamsasImport_actionPerformed(ActionEvent e)
1910 if (v_client == null)
1912 // Load and try to start a session.
1913 JalviewFileChooser chooser = new JalviewFileChooser(
1914 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1916 chooser.setFileView(new JalviewFileView());
1917 chooser.setDialogTitle(MessageManager
1918 .getString("label.open_saved_vamsas_session"));
1919 chooser.setToolTipText(MessageManager
1920 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1922 int value = chooser.showOpenDialog(this);
1924 if (value == JalviewFileChooser.APPROVE_OPTION)
1926 String fle = chooser.getSelectedFile().toString();
1927 if (!vamsasImport(chooser.getSelectedFile()))
1930 .showInternalMessageDialog(
1932 MessageManager.formatMessage(
1933 "label.couldnt_import_as_vamsas_session",
1934 new Object[] { fle }),
1936 .getString("label.vamsas_document_import_failed"),
1937 JvOptionPane.ERROR_MESSAGE);
1943 jalview.bin.Cache.log
1944 .error("Implementation error - load session from a running session is not supported.");
1949 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1952 * @return true if import was a success and a session was started.
1954 public boolean vamsasImport(URL url)
1956 // TODO: create progress bar
1957 if (v_client != null)
1960 jalview.bin.Cache.log
1961 .error("Implementation error - load session from a running session is not supported.");
1967 // copy the URL content to a temporary local file
1968 // TODO: be a bit cleverer here with nio (?!)
1969 File file = File.createTempFile("vdocfromurl", ".vdj");
1970 FileOutputStream fos = new FileOutputStream(file);
1971 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1972 byte[] buffer = new byte[2048];
1974 while ((ln = bis.read(buffer)) > -1)
1976 fos.write(buffer, 0, ln);
1980 v_client = new jalview.gui.VamsasApplication(this, file,
1981 url.toExternalForm());
1982 } catch (Exception ex)
1984 jalview.bin.Cache.log.error(
1985 "Failed to create new vamsas session from contents of URL "
1989 setupVamsasConnectedGui();
1990 v_client.initial_update(); // TODO: thread ?
1991 return v_client.inSession();
1995 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1998 * @return true if import was a success and a session was started.
2000 public boolean vamsasImport(File file)
2002 if (v_client != null)
2005 jalview.bin.Cache.log
2006 .error("Implementation error - load session from a running session is not supported.");
2010 setProgressBar(MessageManager.formatMessage(
2011 "status.importing_vamsas_session_from",
2012 new Object[] { file.getName() }), file.hashCode());
2015 v_client = new jalview.gui.VamsasApplication(this, file, null);
2016 } catch (Exception ex)
2018 setProgressBar(MessageManager.formatMessage(
2019 "status.importing_vamsas_session_from",
2020 new Object[] { file.getName() }), file.hashCode());
2021 jalview.bin.Cache.log.error(
2022 "New vamsas session from existing session file failed:", ex);
2025 setupVamsasConnectedGui();
2026 v_client.initial_update(); // TODO: thread ?
2027 setProgressBar(MessageManager.formatMessage(
2028 "status.importing_vamsas_session_from",
2029 new Object[] { file.getName() }), file.hashCode());
2030 return v_client.inSession();
2033 public boolean joinVamsasSession(String mysesid)
2035 if (v_client != null)
2039 .getString("error.try_join_vamsas_session_another"));
2041 if (mysesid == null)
2044 MessageManager.getString("error.invalid_vamsas_session_id"));
2046 v_client = new VamsasApplication(this, mysesid);
2047 setupVamsasConnectedGui();
2048 v_client.initial_update();
2049 return (v_client.inSession());
2053 public void vamsasStart_actionPerformed(ActionEvent e)
2055 if (v_client == null)
2058 // we just start a default session for moment.
2060 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2061 * getProperty("LAST_DIRECTORY"));
2063 * chooser.setFileView(new JalviewFileView());
2064 * chooser.setDialogTitle("Load Vamsas file");
2065 * chooser.setToolTipText("Import");
2067 * int value = chooser.showOpenDialog(this);
2069 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2070 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2072 v_client = new VamsasApplication(this);
2073 setupVamsasConnectedGui();
2074 v_client.initial_update(); // TODO: thread ?
2078 // store current data in session.
2079 v_client.push_update(); // TODO: thread
2083 protected void setupVamsasConnectedGui()
2085 vamsasStart.setText(MessageManager.getString("label.session_update"));
2086 vamsasSave.setVisible(true);
2087 vamsasStop.setVisible(true);
2088 vamsasImport.setVisible(false); // Document import to existing session is
2089 // not possible for vamsas-client-1.0.
2092 protected void setupVamsasDisconnectedGui()
2094 vamsasSave.setVisible(false);
2095 vamsasStop.setVisible(false);
2096 vamsasImport.setVisible(true);
2097 vamsasStart.setText(MessageManager
2098 .getString("label.new_vamsas_session"));
2102 public void vamsasStop_actionPerformed(ActionEvent e)
2104 if (v_client != null)
2106 v_client.end_session();
2108 setupVamsasDisconnectedGui();
2112 protected void buildVamsasStMenu()
2114 if (v_client == null)
2116 String[] sess = null;
2119 sess = VamsasApplication.getSessionList();
2120 } catch (Exception e)
2122 jalview.bin.Cache.log.warn(
2123 "Problem getting current sessions list.", e);
2128 jalview.bin.Cache.log.debug("Got current sessions list: "
2129 + sess.length + " entries.");
2130 VamsasStMenu.removeAll();
2131 for (int i = 0; i < sess.length; i++)
2133 JMenuItem sessit = new JMenuItem();
2134 sessit.setText(sess[i]);
2135 sessit.setToolTipText(MessageManager.formatMessage(
2136 "label.connect_to_session", new Object[] { sess[i] }));
2137 final Desktop dsktp = this;
2138 final String mysesid = sess[i];
2139 sessit.addActionListener(new ActionListener()
2143 public void actionPerformed(ActionEvent e)
2145 if (dsktp.v_client == null)
2147 Thread rthr = new Thread(new Runnable()
2153 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2154 dsktp.setupVamsasConnectedGui();
2155 dsktp.v_client.initial_update();
2163 VamsasStMenu.add(sessit);
2165 // don't show an empty menu.
2166 VamsasStMenu.setVisible(sess.length > 0);
2171 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2172 VamsasStMenu.removeAll();
2173 VamsasStMenu.setVisible(false);
2178 // Not interested in the content. Just hide ourselves.
2179 VamsasStMenu.setVisible(false);
2184 public void vamsasSave_actionPerformed(ActionEvent e)
2186 if (v_client != null)
2188 // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2189 JalviewFileChooser chooser = new JalviewFileChooser("vdj",
2192 chooser.setFileView(new JalviewFileView());
2193 chooser.setDialogTitle(MessageManager
2194 .getString("label.save_vamsas_document_archive"));
2196 int value = chooser.showSaveDialog(this);
2198 if (value == JalviewFileChooser.APPROVE_OPTION)
2200 java.io.File choice = chooser.getSelectedFile();
2201 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2202 "label.saving_vamsas_doc",
2203 new Object[] { choice.getName() }));
2204 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2205 String warnmsg = null;
2206 String warnttl = null;
2209 v_client.vclient.storeDocument(choice);
2212 warnttl = "Serious Problem saving Vamsas Document";
2213 warnmsg = ex.toString();
2214 jalview.bin.Cache.log.error("Error Whilst saving document to "
2217 } catch (Exception ex)
2219 warnttl = "Problem saving Vamsas Document.";
2220 warnmsg = ex.toString();
2221 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2225 removeProgressPanel(progpanel);
2226 if (warnmsg != null)
2228 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2230 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2236 JPanel vamUpdate = null;
2239 * hide vamsas user gui bits when a vamsas document event is being handled.
2242 * true to hide gui, false to reveal gui
2244 public void setVamsasUpdate(boolean b)
2246 Cache.log.debug("Setting gui for Vamsas update "
2247 + (b ? "in progress" : "finished"));
2249 if (vamUpdate != null)
2251 this.removeProgressPanel(vamUpdate);
2255 vamUpdate = this.addProgressPanel(MessageManager
2256 .getString("label.updating_vamsas_session"));
2258 vamsasStart.setVisible(!b);
2259 vamsasStop.setVisible(!b);
2260 vamsasSave.setVisible(!b);
2263 public JInternalFrame[] getAllFrames()
2265 return desktop.getAllFrames();
2269 * Checks the given url to see if it gives a response indicating that the user
2270 * should be informed of a new questionnaire.
2274 public void checkForQuestionnaire(String url)
2276 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2277 // javax.swing.SwingUtilities.invokeLater(jvq);
2278 new Thread(jvq).start();
2281 public void checkURLLinks()
2283 // Thread off the URL link checker
2284 addDialogThread(new Runnable()
2289 if (Cache.getDefault("CHECKURLLINKS", true))
2291 // check what the actual links are - if it's just the default don't
2292 // bother with the warning
2293 Vector<String> links = Preferences.sequenceURLLinks;
2295 // only need to check links if there is one with a
2296 // SEQUENCE_ID which is not the default EMBL_EBI link
2297 ListIterator<String> li = links.listIterator();
2298 boolean check = false;
2299 List<JLabel> urls = new ArrayList<JLabel>();
2300 while (li.hasNext())
2302 String link = li.next();
2303 if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
2306 int barPos = link.indexOf("|");
2307 String urlMsg = barPos == -1 ? link : link.substring(0,
2308 barPos) + ": " + link.substring(barPos + 1);
2309 urls.add(new JLabel(urlMsg));
2317 // ask user to check in case URL links use old style tokens
2318 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2319 JPanel msgPanel = new JPanel();
2320 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2321 msgPanel.add(Box.createVerticalGlue());
2322 JLabel msg = new JLabel(
2324 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2325 JLabel msg2 = new JLabel(
2327 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2329 for (JLabel url : urls)
2335 final JCheckBox jcb = new JCheckBox(
2336 MessageManager.getString("label.do_not_display_again"));
2337 jcb.addActionListener(new ActionListener()
2340 public void actionPerformed(ActionEvent e)
2342 // update Cache settings for "don't show this again"
2343 boolean showWarningAgain = !jcb.isSelected();
2344 Cache.setProperty("CHECKURLLINKS",
2345 Boolean.valueOf(showWarningAgain).toString());
2350 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2352 .getString("label.SEQUENCE_ID_no_longer_used"),
2353 JvOptionPane.WARNING_MESSAGE);
2360 * Proxy class for JDesktopPane which optionally displays the current memory
2361 * usage and highlights the desktop area with a red bar if free memory runs
2366 public class MyDesktopPane extends JDesktopPane implements Runnable
2369 private static final float ONE_MB = 1048576f;
2371 boolean showMemoryUsage = false;
2375 java.text.NumberFormat df;
2377 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2380 public MyDesktopPane(boolean showMemoryUsage)
2382 showMemoryUsage(showMemoryUsage);
2385 public void showMemoryUsage(boolean showMemory)
2387 this.showMemoryUsage = showMemory;
2390 Thread worker = new Thread(this);
2395 public boolean isShowMemoryUsage()
2397 return showMemoryUsage;
2403 df = java.text.NumberFormat.getNumberInstance();
2404 df.setMaximumFractionDigits(2);
2405 runtime = Runtime.getRuntime();
2407 while (showMemoryUsage)
2411 maxMemory = runtime.maxMemory() / ONE_MB;
2412 allocatedMemory = runtime.totalMemory() / ONE_MB;
2413 freeMemory = runtime.freeMemory() / ONE_MB;
2414 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2416 percentUsage = (totalFreeMemory / maxMemory) * 100;
2418 // if (percentUsage < 20)
2420 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2422 // instance.set.setBorder(border1);
2425 // sleep after showing usage
2427 } catch (Exception ex)
2429 ex.printStackTrace();
2435 public void paintComponent(Graphics g)
2437 if (showMemoryUsage && g != null && df != null)
2439 if (percentUsage < 20)
2441 g.setColor(Color.red);
2443 FontMetrics fm = g.getFontMetrics();
2446 g.drawString(MessageManager.formatMessage(
2447 "label.memory_stats",
2448 new Object[] { df.format(totalFreeMemory),
2449 df.format(maxMemory), df.format(percentUsage) }), 10,
2450 getHeight() - fm.getHeight());
2457 * fixes stacking order after a modal dialog to ensure windows that should be
2458 * on top actually are
2460 public void relayerWindows()
2465 protected JMenuItem groovyShell;
2468 * Accessor method to quickly get all the AlignmentFrames loaded.
2470 * @return an array of AlignFrame, or null if none found
2472 public static AlignFrame[] getAlignFrames()
2474 if (Jalview.isHeadlessMode())
2476 // Desktop.desktop is null in headless mode
2477 return new AlignFrame[] { Jalview.currentAlignFrame };
2480 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2486 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2488 for (int i = frames.length - 1; i > -1; i--)
2490 if (frames[i] instanceof AlignFrame)
2492 avp.add((AlignFrame) frames[i]);
2494 else if (frames[i] instanceof SplitFrame)
2497 * Also check for a split frame containing an AlignFrame
2499 GSplitFrame sf = (GSplitFrame) frames[i];
2500 if (sf.getTopFrame() instanceof AlignFrame)
2502 avp.add((AlignFrame) sf.getTopFrame());
2504 if (sf.getBottomFrame() instanceof AlignFrame)
2506 avp.add((AlignFrame) sf.getBottomFrame());
2510 if (avp.size() == 0)
2514 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2519 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2523 public GStructureViewer[] getJmols()
2525 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2531 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2533 for (int i = frames.length - 1; i > -1; i--)
2535 if (frames[i] instanceof AppJmol)
2537 GStructureViewer af = (GStructureViewer) frames[i];
2541 if (avp.size() == 0)
2545 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2550 * Add Groovy Support to Jalview
2552 public void groovyShell_actionPerformed()
2556 openGroovyConsole();
2557 } catch (Exception ex)
2559 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2560 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2562 MessageManager.getString("label.couldnt_create_groovy_shell"),
2563 MessageManager.getString("label.groovy_support_failed"),
2564 JvOptionPane.ERROR_MESSAGE);
2569 * Open the Groovy console
2571 void openGroovyConsole()
2573 if (groovyConsole == null)
2575 groovyConsole = new groovy.ui.Console();
2576 groovyConsole.setVariable("Jalview", this);
2577 groovyConsole.run();
2580 * We allow only one console at a time, so that AlignFrame menu option
2581 * 'Calculate | Run Groovy script' is unambiguous.
2582 * Disable 'Groovy Console', and enable 'Run script', when the console is
2583 * opened, and the reverse when it is closed
2585 Window window = (Window) groovyConsole.getFrame();
2586 window.addWindowListener(new WindowAdapter()
2589 public void windowClosed(WindowEvent e)
2592 * rebind CMD-Q from Groovy Console to Jalview Quit
2595 enableExecuteGroovy(false);
2601 * show Groovy console window (after close and reopen)
2603 ((Window) groovyConsole.getFrame()).setVisible(true);
2606 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2607 * and disable opening a second console
2609 enableExecuteGroovy(true);
2613 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2614 * binding when opened
2616 protected void addQuitHandler()
2618 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2619 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2620 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2621 getRootPane().getActionMap().put("Quit", new AbstractAction()
2624 public void actionPerformed(ActionEvent e)
2632 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2635 * true if Groovy console is open
2637 public void enableExecuteGroovy(boolean enabled)
2640 * disable opening a second Groovy console
2641 * (or re-enable when the console is closed)
2643 groovyShell.setEnabled(!enabled);
2645 AlignFrame[] alignFrames = getAlignFrames();
2646 if (alignFrames != null)
2648 for (AlignFrame af : alignFrames)
2650 af.setGroovyEnabled(enabled);
2656 * Progress bars managed by the IProgressIndicator method.
2658 private Hashtable<Long, JPanel> progressBars;
2660 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2665 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2668 public void setProgressBar(String message, long id)
2670 if (progressBars == null)
2672 progressBars = new Hashtable<Long, JPanel>();
2673 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2676 if (progressBars.get(new Long(id)) != null)
2678 JPanel panel = progressBars.remove(new Long(id));
2679 if (progressBarHandlers.contains(new Long(id)))
2681 progressBarHandlers.remove(new Long(id));
2683 removeProgressPanel(panel);
2687 progressBars.put(new Long(id), addProgressPanel(message));
2694 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2695 * jalview.gui.IProgressIndicatorHandler)
2698 public void registerHandler(final long id,
2699 final IProgressIndicatorHandler handler)
2701 if (progressBarHandlers == null
2702 || !progressBars.containsKey(new Long(id)))
2706 .getString("error.call_setprogressbar_before_registering_handler"));
2708 progressBarHandlers.put(new Long(id), handler);
2709 final JPanel progressPanel = progressBars.get(new Long(id));
2710 if (handler.canCancel())
2712 JButton cancel = new JButton(
2713 MessageManager.getString("action.cancel"));
2714 final IProgressIndicator us = this;
2715 cancel.addActionListener(new ActionListener()
2719 public void actionPerformed(ActionEvent e)
2721 handler.cancelActivity(id);
2722 us.setProgressBar(MessageManager.formatMessage(
2723 "label.cancelled_params",
2724 new Object[] { ((JLabel) progressPanel.getComponent(0))
2728 progressPanel.add(cancel, BorderLayout.EAST);
2734 * @return true if any progress bars are still active
2737 public boolean operationInProgress()
2739 if (progressBars != null && progressBars.size() > 0)
2747 * This will return the first AlignFrame holding the given viewport instance.
2748 * It will break if there are more than one AlignFrames viewing a particular
2752 * @return alignFrame for viewport
2754 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2756 if (desktop != null)
2758 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2759 for (int panel = 0; aps != null && panel < aps.length; panel++)
2761 if (aps[panel] != null && aps[panel].av == viewport)
2763 return aps[panel].alignFrame;
2770 public VamsasApplication getVamsasApplication()
2777 * flag set if jalview GUI is being operated programmatically
2779 private boolean inBatchMode = false;
2782 * check if jalview GUI is being operated programmatically
2784 * @return inBatchMode
2786 public boolean isInBatchMode()
2792 * set flag if jalview GUI is being operated programmatically
2794 * @param inBatchMode
2796 public void setInBatchMode(boolean inBatchMode)
2798 this.inBatchMode = inBatchMode;
2801 public void startServiceDiscovery()
2803 startServiceDiscovery(false);
2806 public void startServiceDiscovery(boolean blocking)
2808 boolean alive = true;
2809 Thread t0 = null, t1 = null, t2 = null;
2810 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2813 // todo: changesupport handlers need to be transferred
2814 if (discoverer == null)
2816 discoverer = new jalview.ws.jws1.Discoverer();
2817 // register PCS handler for desktop.
2818 discoverer.addPropertyChangeListener(changeSupport);
2820 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2821 // until we phase out completely
2822 (t0 = new Thread(discoverer)).start();
2825 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2827 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2829 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2831 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2837 // TODO: do rest service discovery
2846 } catch (Exception e)
2849 alive = (t1 != null && t1.isAlive())
2850 || (t2 != null && t2.isAlive())
2851 || (t3 != null && t3.isAlive())
2852 || (t0 != null && t0.isAlive());
2858 * called to check if the service discovery process completed successfully.
2862 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2864 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2866 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2867 .getErrorMessages();
2870 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2872 if (serviceChangedDialog == null)
2874 // only run if we aren't already displaying one of these.
2875 addDialogThread(serviceChangedDialog = new Runnable()
2882 * JalviewDialog jd =new JalviewDialog() {
2884 * @Override protected void cancelPressed() { // TODO
2885 * Auto-generated method stub
2887 * }@Override protected void okPressed() { // TODO
2888 * Auto-generated method stub
2890 * }@Override protected void raiseClosed() { // TODO
2891 * Auto-generated method stub
2893 * } }; jd.initDialogFrame(new
2894 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2895 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2896 * + " or mis-configured HTTP proxy settings.<br/>" +
2897 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2899 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2900 * ), true, true, "Web Service Configuration Problem", 450,
2903 * jd.waitForInput();
2909 "<html><table width=\"450\"><tr><td>"
2911 + "</td></tr></table>"
2912 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2913 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2914 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2915 + " Tools->Preferences dialog box to change them.</p></html>"),
2916 "Web Service Configuration Problem",
2917 JvOptionPane.DEFAULT_OPTION,
2918 JvOptionPane.ERROR_MESSAGE);
2919 serviceChangedDialog = null;
2928 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2935 private Runnable serviceChangedDialog = null;
2938 * start a thread to open a URL in the configured browser. Pops up a warning
2939 * dialog to the user if there is an exception when calling out to the browser
2944 public static void showUrl(final String url)
2946 showUrl(url, Desktop.instance);
2950 * Like showUrl but allows progress handler to be specified
2954 * (null) or object implementing IProgressIndicator
2956 public static void showUrl(final String url,
2957 final IProgressIndicator progress)
2959 new Thread(new Runnable()
2966 if (progress != null)
2968 progress.setProgressBar(MessageManager.formatMessage(
2969 "status.opening_params", new Object[] { url }), this
2972 jalview.util.BrowserLauncher.openURL(url);
2973 } catch (Exception ex)
2975 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2977 .getString("label.web_browser_not_found_unix"),
2978 MessageManager.getString("label.web_browser_not_found"),
2979 JvOptionPane.WARNING_MESSAGE);
2981 ex.printStackTrace();
2983 if (progress != null)
2985 progress.setProgressBar(null, this.hashCode());
2991 public static WsParamSetManager wsparamManager = null;
2993 public static ParamManager getUserParameterStore()
2995 if (wsparamManager == null)
2997 wsparamManager = new WsParamSetManager();
2999 return wsparamManager;
3003 * static hyperlink handler proxy method for use by Jalview's internal windows
3007 public static void hyperlinkUpdate(HyperlinkEvent e)
3009 if (e.getEventType() == EventType.ACTIVATED)
3014 url = e.getURL().toString();
3015 Desktop.showUrl(url);
3016 } catch (Exception x)
3020 if (Cache.log != null)
3022 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3026 System.err.println("Couldn't handle string " + url
3030 // ignore any exceptions due to dud links.
3037 * single thread that handles display of dialogs to user.
3039 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3042 * flag indicating if dialogExecutor should try to acquire a permit
3044 private volatile boolean dialogPause = true;
3049 private java.util.concurrent.Semaphore block = new Semaphore(0);
3051 private static groovy.ui.Console groovyConsole;
3054 * add another dialog thread to the queue
3058 public void addDialogThread(final Runnable prompter)
3060 dialogExecutor.submit(new Runnable()
3070 } catch (InterruptedException x)
3075 if (instance == null)
3081 SwingUtilities.invokeAndWait(prompter);
3082 } catch (Exception q)
3084 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3090 public void startDialogQueue()
3092 // set the flag so we don't pause waiting for another permit and semaphore
3093 // the current task to begin
3094 dialogPause = false;
3099 protected void snapShotWindow_actionPerformed(ActionEvent e)
3103 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3104 "View of Desktop", getWidth(), getHeight(), of = new File(
3105 "Jalview_snapshot" + System.currentTimeMillis()
3106 + ".eps"), "View of desktop", null, 0, false);
3109 paintAll(im.getGraphics());
3111 } catch (Exception q)
3113 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3117 Cache.log.info("Successfully written snapshot to file "
3118 + of.getAbsolutePath());
3122 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3123 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3124 * and location last time the view was expanded (if any). However it does not
3125 * remember the split pane divider location - this is set to match the
3126 * 'exploding' frame.
3130 public void explodeViews(SplitFrame sf)
3132 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3133 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3134 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3136 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3138 int viewCount = topPanels.size();
3145 * Processing in reverse order works, forwards order leaves the first panels
3146 * not visible. I don't know why!
3148 for (int i = viewCount - 1; i >= 0; i--)
3151 * Make new top and bottom frames. These take over the respective
3152 * AlignmentPanel objects, including their AlignmentViewports, so the
3153 * cdna/protein relationships between the viewports is carried over to the
3156 * explodedGeometry holds the (x, y) position of the previously exploded
3157 * SplitFrame, and the (width, height) of the AlignFrame component
3159 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3160 AlignFrame newTopFrame = new AlignFrame(topPanel);
3161 newTopFrame.setSize(oldTopFrame.getSize());
3162 newTopFrame.setVisible(true);
3163 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3164 .getExplodedGeometry();
3165 if (geometry != null)
3167 newTopFrame.setSize(geometry.getSize());
3170 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3171 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3172 newBottomFrame.setSize(oldBottomFrame.getSize());
3173 newBottomFrame.setVisible(true);
3174 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3175 .getExplodedGeometry();
3176 if (geometry != null)
3178 newBottomFrame.setSize(geometry.getSize());
3181 topPanel.av.setGatherViewsHere(false);
3182 bottomPanel.av.setGatherViewsHere(false);
3183 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3185 if (geometry != null)
3187 splitFrame.setLocation(geometry.getLocation());
3189 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3193 * Clear references to the panels (now relocated in the new SplitFrames)
3194 * before closing the old SplitFrame.
3197 bottomPanels.clear();
3202 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3203 * back into the given SplitFrame as additional views. Note that the gathered
3204 * frames may themselves have multiple views.
3208 public void gatherViews(GSplitFrame source)
3211 * special handling of explodedGeometry for a view within a SplitFrame: - it
3212 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3213 * height) of the AlignFrame component
3215 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3216 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3217 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3218 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3219 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3220 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3222 myTopFrame.viewport.setGatherViewsHere(true);
3223 myBottomFrame.viewport.setGatherViewsHere(true);
3224 String topViewId = myTopFrame.viewport.getSequenceSetId();
3225 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3227 JInternalFrame[] frames = desktop.getAllFrames();
3228 for (JInternalFrame frame : frames)
3230 if (frame instanceof SplitFrame && frame != source)
3232 SplitFrame sf = (SplitFrame) frame;
3233 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3234 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3235 boolean gatherThis = false;
3236 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3238 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3239 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3240 if (topViewId.equals(topPanel.av.getSequenceSetId())
3241 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3244 topPanel.av.setGatherViewsHere(false);
3245 bottomPanel.av.setGatherViewsHere(false);
3246 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3247 topFrame.getSize()));
3248 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3249 .getLocation(), bottomFrame.getSize()));
3250 myTopFrame.addAlignmentPanel(topPanel, false);
3251 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3257 topFrame.getAlignPanels().clear();
3258 bottomFrame.getAlignPanels().clear();
3265 * The dust settles...give focus to the tab we did this from.
3267 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3270 public static groovy.ui.Console getGroovyConsole()
3272 return groovyConsole;
3275 public static void transferFromDropTarget(List<String> files,
3276 List<DataSourceType> protocols, DropTargetDropEvent evt,
3281 DataFlavor uriListFlavor = new DataFlavor(
3282 "text/uri-list;class=java.lang.String");
3283 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3285 // Works on Windows and MacOSX
3286 Cache.log.debug("Drop handled as javaFileListFlavor");
3287 for (Object file : (List) t
3288 .getTransferData(DataFlavor.javaFileListFlavor))
3290 files.add(((File) file).toString());
3291 protocols.add(DataSourceType.FILE);
3296 // Unix like behaviour
3297 boolean added = false;
3299 if (t.isDataFlavorSupported(uriListFlavor))
3301 Cache.log.debug("Drop handled as uriListFlavor");
3302 // This is used by Unix drag system
3303 data = (String) t.getTransferData(uriListFlavor);
3307 // fallback to text: workaround - on OSX where there's a JVM bug
3308 Cache.log.debug("standard URIListFlavor failed. Trying text");
3309 // try text fallback
3310 data = (String) t.getTransferData(new DataFlavor(
3311 "text/plain;class=java.lang.String"));
3312 if (Cache.log.isDebugEnabled())
3314 Cache.log.debug("fallback returned " + data);
3317 while (protocols.size() < files.size())
3319 Cache.log.debug("Adding missing FILE protocol for "
3320 + files.get(protocols.size()));
3321 protocols.add(DataSourceType.FILE);
3323 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3324 data, "\r\n"); st.hasMoreTokens();)
3327 String s = st.nextToken();
3328 if (s.startsWith("#"))
3330 // the line is a comment (as per the RFC 2483)
3333 java.net.URI uri = new java.net.URI(s);
3334 if (uri.getScheme().toLowerCase().startsWith("http"))
3336 protocols.add(DataSourceType.URL);
3337 files.add(uri.toString());
3341 // otherwise preserve old behaviour: catch all for file objects
3342 java.io.File file = new java.io.File(uri);
3343 protocols.add(DataSourceType.FILE);
3344 files.add(file.toString());
3347 if (Cache.log.isDebugEnabled())
3349 if (data == null || !added)
3352 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3353 for (DataFlavor fl : t.getTransferDataFlavors())
3355 Cache.log.debug("Supported transfer dataflavor: "
3357 Object df = t.getTransferData(fl);
3360 Cache.log.debug("Retrieves: " + df);
3364 Cache.log.debug("Retrieved nothing");