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.FileLoader;
30 import jalview.io.FormatAdapter;
31 import jalview.io.IdentifyFile;
32 import jalview.io.JalviewFileChooser;
33 import jalview.io.JalviewFileView;
34 import jalview.jbgui.GSplitFrame;
35 import jalview.jbgui.GStructureViewer;
36 import jalview.structure.StructureSelectionManager;
37 import jalview.urls.UrlProviderI;
38 import jalview.util.ImageMaker;
39 import jalview.util.MessageManager;
40 import jalview.util.Platform;
41 import jalview.viewmodel.AlignmentViewport;
42 import jalview.ws.params.ParamManager;
44 import java.awt.BorderLayout;
45 import java.awt.Color;
46 import java.awt.Dimension;
47 import java.awt.FontMetrics;
48 import java.awt.Graphics;
49 import java.awt.GridLayout;
50 import java.awt.Point;
51 import java.awt.Rectangle;
52 import java.awt.Toolkit;
53 import java.awt.Window;
54 import java.awt.datatransfer.Clipboard;
55 import java.awt.datatransfer.ClipboardOwner;
56 import java.awt.datatransfer.DataFlavor;
57 import java.awt.datatransfer.Transferable;
58 import java.awt.dnd.DnDConstants;
59 import java.awt.dnd.DropTargetDragEvent;
60 import java.awt.dnd.DropTargetDropEvent;
61 import java.awt.dnd.DropTargetEvent;
62 import java.awt.dnd.DropTargetListener;
63 import java.awt.event.ActionEvent;
64 import java.awt.event.ActionListener;
65 import java.awt.event.FocusEvent;
66 import java.awt.event.FocusListener;
67 import java.awt.event.KeyEvent;
68 import java.awt.event.MouseAdapter;
69 import java.awt.event.MouseEvent;
70 import java.awt.event.WindowAdapter;
71 import java.awt.event.WindowEvent;
72 import java.beans.PropertyChangeEvent;
73 import java.beans.PropertyChangeListener;
74 import java.io.BufferedInputStream;
76 import java.io.FileOutputStream;
78 import java.util.ArrayList;
79 import java.util.Hashtable;
80 import java.util.List;
81 import java.util.ListIterator;
82 import java.util.StringTokenizer;
83 import java.util.Vector;
84 import java.util.concurrent.ExecutorService;
85 import java.util.concurrent.Executors;
86 import java.util.concurrent.Semaphore;
88 import javax.swing.AbstractAction;
89 import javax.swing.Box;
90 import javax.swing.BoxLayout;
91 import javax.swing.DefaultDesktopManager;
92 import javax.swing.DesktopManager;
93 import javax.swing.JButton;
94 import javax.swing.JCheckBox;
95 import javax.swing.JComboBox;
96 import javax.swing.JComponent;
97 import javax.swing.JDesktopPane;
98 import javax.swing.JFrame;
99 import javax.swing.JInternalFrame;
100 import javax.swing.JLabel;
101 import javax.swing.JMenuItem;
102 import javax.swing.JOptionPane;
103 import javax.swing.JPanel;
104 import javax.swing.JPopupMenu;
105 import javax.swing.JProgressBar;
106 import javax.swing.KeyStroke;
107 import javax.swing.SwingUtilities;
108 import javax.swing.event.HyperlinkEvent;
109 import javax.swing.event.HyperlinkEvent.EventType;
110 import javax.swing.event.InternalFrameAdapter;
111 import javax.swing.event.InternalFrameEvent;
112 import javax.swing.event.MenuEvent;
113 import javax.swing.event.MenuListener;
120 * @version $Revision: 1.155 $
122 public class Desktop extends jalview.jbgui.GDesktop implements
123 DropTargetListener, ClipboardOwner, IProgressIndicator,
124 jalview.api.StructureSelectionManagerProvider
127 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
130 * news reader - null if it was never started.
132 private BlogReader jvnews = null;
134 private File projectFile;
138 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
140 public void addJalviewPropertyChangeListener(
141 PropertyChangeListener listener)
143 changeSupport.addJalviewPropertyChangeListener(listener);
147 * @param propertyName
149 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
150 * java.beans.PropertyChangeListener)
152 public void addJalviewPropertyChangeListener(String propertyName,
153 PropertyChangeListener listener)
155 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
159 * @param propertyName
161 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
162 * java.beans.PropertyChangeListener)
164 public void removeJalviewPropertyChangeListener(String propertyName,
165 PropertyChangeListener listener)
167 changeSupport.removeJalviewPropertyChangeListener(propertyName,
171 /** Singleton Desktop instance */
172 public static Desktop instance;
174 public static MyDesktopPane desktop;
176 static int openFrameCount = 0;
178 static final int xOffset = 30;
180 static final int yOffset = 30;
182 public static jalview.ws.jws1.Discoverer discoverer;
184 public static Object[] jalviewClipboard;
186 public static boolean internalCopy = false;
188 static int fileLoadingCount = 0;
190 class MyDesktopManager implements DesktopManager
193 private DesktopManager delegate;
195 public MyDesktopManager(DesktopManager delegate)
197 this.delegate = delegate;
201 public void activateFrame(JInternalFrame f)
205 delegate.activateFrame(f);
206 } catch (NullPointerException npe)
208 Point p = getMousePosition();
209 instance.showPasteMenu(p.x, p.y);
214 public void beginDraggingFrame(JComponent f)
216 delegate.beginDraggingFrame(f);
220 public void beginResizingFrame(JComponent f, int direction)
222 delegate.beginResizingFrame(f, direction);
226 public void closeFrame(JInternalFrame f)
228 delegate.closeFrame(f);
232 public void deactivateFrame(JInternalFrame f)
234 delegate.deactivateFrame(f);
238 public void deiconifyFrame(JInternalFrame f)
240 delegate.deiconifyFrame(f);
244 public void dragFrame(JComponent f, int newX, int newY)
250 delegate.dragFrame(f, newX, newY);
254 public void endDraggingFrame(JComponent f)
256 delegate.endDraggingFrame(f);
260 public void endResizingFrame(JComponent f)
262 delegate.endResizingFrame(f);
266 public void iconifyFrame(JInternalFrame f)
268 delegate.iconifyFrame(f);
272 public void maximizeFrame(JInternalFrame f)
274 delegate.maximizeFrame(f);
278 public void minimizeFrame(JInternalFrame f)
280 delegate.minimizeFrame(f);
284 public void openFrame(JInternalFrame f)
286 delegate.openFrame(f);
290 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
297 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
301 public void setBoundsForFrame(JComponent f, int newX, int newY,
302 int newWidth, int newHeight)
304 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
307 // All other methods, simply delegate
312 * Creates a new Desktop object.
317 * A note to implementors. It is ESSENTIAL that any activities that might
318 * block are spawned off as threads rather than waited for during this
322 doVamsasClientCheck();
324 groovyShell = new JMenuItem();
325 groovyShell.setText(MessageManager.getString("label.groovy_console"));
326 groovyShell.addActionListener(new ActionListener()
329 public void actionPerformed(ActionEvent e)
331 groovyShell_actionPerformed();
334 toolsMenu.add(groovyShell);
335 groovyShell.setVisible(true);
337 doConfigureStructurePrefs();
338 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
339 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
340 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
342 boolean showjconsole = jalview.bin.Cache.getDefault(
343 "SHOW_JAVA_CONSOLE", false);
344 desktop = new MyDesktopPane(selmemusage);
345 if (Platform.isAMac())
347 desktop.setDoubleBuffered(false);
349 showMemusage.setSelected(selmemusage);
350 desktop.setBackground(Color.white);
351 getContentPane().setLayout(new BorderLayout());
352 // alternate config - have scrollbars - see notes in JAL-153
353 // JScrollPane sp = new JScrollPane();
354 // sp.getViewport().setView(desktop);
355 // getContentPane().add(sp, BorderLayout.CENTER);
356 getContentPane().add(desktop, BorderLayout.CENTER);
357 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
359 // This line prevents Windows Look&Feel resizing all new windows to maximum
360 // if previous window was maximised
361 desktop.setDesktopManager(new MyDesktopManager(
362 new DefaultDesktopManager()));
364 Rectangle dims = getLastKnownDimensions("");
371 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
372 setBounds((screenSize.width - 900) / 2,
373 (screenSize.height - 650) / 2, 900, 650);
375 jconsole = new Console(this, showjconsole);
376 // add essential build information
377 jconsole.setHeader("Jalview Version: "
378 + jalview.bin.Cache.getProperty("VERSION") + "\n"
379 + "Jalview Installation: "
380 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
381 + "\n" + "Build Date: "
382 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
383 + "Java version: " + System.getProperty("java.version") + "\n"
384 + System.getProperty("os.arch") + " "
385 + System.getProperty("os.name") + " "
386 + System.getProperty("os.version"));
388 showConsole(showjconsole);
390 showNews.setVisible(false);
394 this.addWindowListener(new WindowAdapter()
397 public void windowClosing(WindowEvent evt)
404 this.addMouseListener(ma = new MouseAdapter()
407 public void mousePressed(MouseEvent evt)
409 if (evt.isPopupTrigger()) // Mac
411 showPasteMenu(evt.getX(), evt.getY());
416 public void mouseReleased(MouseEvent evt)
418 if (evt.isPopupTrigger()) // Windows
420 showPasteMenu(evt.getX(), evt.getY());
424 desktop.addMouseListener(ma);
426 this.addFocusListener(new FocusListener()
430 public void focusLost(FocusEvent e)
432 // TODO Auto-generated method stub
437 public void focusGained(FocusEvent e)
439 Cache.log.debug("Relaying windows after focus gain");
440 // make sure that we sort windows properly after we gain focus
441 instance.relayerWindows();
444 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
445 // Spawn a thread that shows the splashscreen
446 SwingUtilities.invokeLater(new Runnable()
456 // Thread off a new instance of the file chooser - this reduces the time it
457 // takes to open it later on.
458 new Thread(new Runnable()
463 Cache.log.debug("Filechooser init thread started.");
464 new JalviewFileChooser(
465 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
466 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
467 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
468 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
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 String format = new IdentifyFile().identify(file,
689 FormatAdapter.PASTE);
691 new FileLoader().LoadFile(file, FormatAdapter.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)
894 windowMenu.add(menuItem);
900 frame.setSelected(true);
901 frame.requestFocus();
902 } catch (java.beans.PropertyVetoException ve)
904 } catch (java.lang.ClassCastException cex)
907 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
913 public void lostOwnership(Clipboard clipboard, Transferable contents)
917 Desktop.jalviewClipboard = null;
920 internalCopy = false;
924 public void dragEnter(DropTargetDragEvent evt)
929 public void dragExit(DropTargetEvent evt)
934 public void dragOver(DropTargetDragEvent evt)
939 public void dropActionChanged(DropTargetDragEvent evt)
950 public void drop(DropTargetDropEvent evt)
952 boolean success = true;
953 // JAL-1552 - acceptDrop required before getTransferable call for
954 // Java's Transferable for native dnd
955 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
956 Transferable t = evt.getTransferable();
957 java.util.List<String> files = new ArrayList<String>();
958 java.util.List<String> protocols = new ArrayList<String>();
962 Desktop.transferFromDropTarget(files, protocols, evt, t);
963 } catch (Exception e)
973 for (int i = 0; i < files.size(); i++)
975 String file = files.get(i).toString();
976 String protocol = (protocols == null) ? FormatAdapter.FILE
977 : (String) protocols.get(i);
978 String format = null;
980 if (file.endsWith(".jar"))
987 format = new IdentifyFile().identify(file, protocol);
990 new FileLoader().LoadFile(file, protocol, format);
993 } catch (Exception ex)
998 evt.dropComplete(success); // need this to ensure input focus is properly
999 // transfered to any new windows created
1009 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1011 JalviewFileChooser chooser = new JalviewFileChooser(
1012 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1013 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
1014 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
1015 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
1017 chooser.setFileView(new JalviewFileView());
1018 chooser.setDialogTitle(MessageManager
1019 .getString("label.open_local_file"));
1020 chooser.setToolTipText(MessageManager.getString("action.open"));
1022 int value = chooser.showOpenDialog(this);
1024 if (value == JalviewFileChooser.APPROVE_OPTION)
1026 String choice = chooser.getSelectedFile().getPath();
1027 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1028 .getSelectedFile().getParent());
1030 String format = null;
1031 if (chooser.getSelectedFormat() != null
1032 && chooser.getSelectedFormat().equals("Jalview"))
1038 format = new IdentifyFile().identify(choice, FormatAdapter.FILE);
1041 if (viewport != null)
1043 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
1048 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
1060 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1062 // This construct allows us to have a wider textfield
1064 JLabel label = new JLabel(
1065 MessageManager.getString("label.input_file_url"));
1066 final JComboBox history = new JComboBox();
1068 JPanel panel = new JPanel(new GridLayout(2, 1));
1071 history.setPreferredSize(new Dimension(400, 20));
1072 history.setEditable(true);
1073 history.addItem("http://www.");
1075 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1079 if (historyItems != null)
1081 st = new StringTokenizer(historyItems, "\t");
1083 while (st.hasMoreTokens())
1085 history.addItem(st.nextElement());
1089 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
1090 MessageManager.getString("label.input_alignment_from_url"),
1091 JOptionPane.OK_CANCEL_OPTION);
1093 if (reply != JOptionPane.OK_OPTION)
1098 String url = history.getSelectedItem().toString();
1100 if (url.toLowerCase().endsWith(".jar"))
1102 if (viewport != null)
1104 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1109 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1114 String format = new IdentifyFile().identify(url, FormatAdapter.URL);
1116 if (format.equals("URL NOT FOUND"))
1118 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1119 MessageManager.formatMessage("label.couldnt_locate",
1120 new Object[] { url }), MessageManager
1121 .getString("label.url_not_found"),
1122 JOptionPane.WARNING_MESSAGE);
1127 if (viewport != null)
1129 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1133 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1139 * Opens the CutAndPaste window for the user to paste an alignment in to
1142 * - if not null, the pasted alignment is added to the current
1143 * alignment; if null, to a new alignment window
1146 public void inputTextboxMenuItem_actionPerformed(
1147 AlignmentViewPanel viewPanel)
1149 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1150 cap.setForInput(viewPanel);
1151 Desktop.addInternalFrame(cap,
1152 MessageManager.getString("label.cut_paste_alignmen_file"),
1162 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1164 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1165 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1167 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1168 getBounds().y, getWidth(), getHeight()));
1170 if (jconsole != null)
1172 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1173 jconsole.stopConsole();
1177 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1180 if (dialogExecutor != null)
1182 dialogExecutor.shutdownNow();
1184 closeAll_actionPerformed(null);
1186 if (groovyConsole != null)
1188 // suppress a possible repeat prompt to save script
1189 groovyConsole.setDirty(false);
1190 groovyConsole.exit();
1195 private void storeLastKnownDimensions(String string, Rectangle jc)
1197 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1198 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1199 + " height:" + jc.height);
1201 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1202 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1203 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1204 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1214 public void aboutMenuItem_actionPerformed(ActionEvent e)
1216 // StringBuffer message = getAboutMessage(false);
1217 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1219 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1220 new Thread(new Runnable()
1225 new SplashScreen(true);
1230 public StringBuffer getAboutMessage(boolean shortv)
1232 StringBuffer message = new StringBuffer();
1233 message.append("<html>");
1236 message.append("<h1><strong>Version: "
1237 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1238 message.append("<strong>Last Updated: <em>"
1239 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1240 + "</em></strong>");
1246 message.append("<strong>Version "
1247 + jalview.bin.Cache.getProperty("VERSION")
1248 + "; last updated: "
1249 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1252 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1255 message.append("<br>...Checking latest version...</br>");
1257 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1258 .equals(jalview.bin.Cache.getProperty("VERSION")))
1260 boolean red = false;
1261 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1262 .indexOf("automated build") == -1)
1265 // Displayed when code version and jnlp version do not match and code
1266 // version is not a development build
1267 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1270 message.append("<br>!! Version "
1271 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1273 + " is available for download from "
1274 + jalview.bin.Cache.getDefault("www.jalview.org",
1275 "http://www.jalview.org") + " !!");
1278 message.append("</div>");
1281 message.append("<br>Authors: "
1283 .getDefault("AUTHORFNAMES",
1284 "The Jalview Authors (See AUTHORS file for current list)")
1285 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1286 + "<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"
1287 + "<br><br>If you use Jalview, please cite:"
1288 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1289 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1290 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1302 public void documentationMenuItem_actionPerformed(ActionEvent e)
1306 Help.showHelpWindow();
1307 } catch (Exception ex)
1313 public void closeAll_actionPerformed(ActionEvent e)
1315 // TODO show a progress bar while closing?
1316 JInternalFrame[] frames = desktop.getAllFrames();
1317 for (int i = 0; i < frames.length; i++)
1321 frames[i].setClosed(true);
1322 } catch (java.beans.PropertyVetoException ex)
1326 Jalview.setCurrentAlignFrame(null);
1327 System.out.println("ALL CLOSED");
1328 if (v_client != null)
1330 // TODO clear binding to vamsas document objects on close_all
1334 * reset state of singleton objects as appropriate (clear down session state
1335 * when all windows are closed)
1337 StructureSelectionManager ssm = StructureSelectionManager
1338 .getStructureSelectionManager(this);
1347 public void raiseRelated_actionPerformed(ActionEvent e)
1349 reorderAssociatedWindows(false, false);
1353 public void minimizeAssociated_actionPerformed(ActionEvent e)
1355 reorderAssociatedWindows(true, false);
1358 void closeAssociatedWindows()
1360 reorderAssociatedWindows(false, true);
1366 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1370 protected void garbageCollect_actionPerformed(ActionEvent e)
1372 // We simply collect the garbage
1373 jalview.bin.Cache.log.debug("Collecting garbage...");
1375 jalview.bin.Cache.log.debug("Finished garbage collection.");
1382 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1386 protected void showMemusage_actionPerformed(ActionEvent e)
1388 desktop.showMemoryUsage(showMemusage.isSelected());
1395 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1399 protected void showConsole_actionPerformed(ActionEvent e)
1401 showConsole(showConsole.isSelected());
1404 Console jconsole = null;
1407 * control whether the java console is visible or not
1411 void showConsole(boolean selected)
1413 showConsole.setSelected(selected);
1414 // TODO: decide if we should update properties file
1415 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1417 jconsole.setVisible(selected);
1420 void reorderAssociatedWindows(boolean minimize, boolean close)
1422 JInternalFrame[] frames = desktop.getAllFrames();
1423 if (frames == null || frames.length < 1)
1428 AlignmentViewport source = null, target = null;
1429 if (frames[0] instanceof AlignFrame)
1431 source = ((AlignFrame) frames[0]).getCurrentView();
1433 else if (frames[0] instanceof TreePanel)
1435 source = ((TreePanel) frames[0]).getViewPort();
1437 else if (frames[0] instanceof PCAPanel)
1439 source = ((PCAPanel) frames[0]).av;
1441 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1443 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1448 for (int i = 0; i < frames.length; i++)
1451 if (frames[i] == null)
1455 if (frames[i] instanceof AlignFrame)
1457 target = ((AlignFrame) frames[i]).getCurrentView();
1459 else if (frames[i] instanceof TreePanel)
1461 target = ((TreePanel) frames[i]).getViewPort();
1463 else if (frames[i] instanceof PCAPanel)
1465 target = ((PCAPanel) frames[i]).av;
1467 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1469 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1472 if (source == target)
1478 frames[i].setClosed(true);
1482 frames[i].setIcon(minimize);
1485 frames[i].toFront();
1489 } catch (java.beans.PropertyVetoException ex)
1504 protected void preferences_actionPerformed(ActionEvent e)
1516 public void saveState_actionPerformed(ActionEvent e)
1518 JalviewFileChooser chooser = new JalviewFileChooser(
1519 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1520 new String[] { "jvp" }, new String[] { "Jalview Project" },
1523 chooser.setFileView(new JalviewFileView());
1524 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1526 int value = chooser.showSaveDialog(this);
1528 if (value == JalviewFileChooser.APPROVE_OPTION)
1530 final Desktop me = this;
1531 final java.io.File choice = chooser.getSelectedFile();
1532 setProjectFile(choice);
1534 new Thread(new Runnable()
1539 // TODO: refactor to Jalview desktop session controller action.
1540 setProgressBar(MessageManager.formatMessage(
1541 "label.saving_jalview_project",
1542 new Object[] { choice.getName() }), choice.hashCode());
1543 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1544 choice.getParent());
1545 // TODO catch and handle errors for savestate
1546 // TODO prevent user from messing with the Desktop whilst we're saving
1549 new Jalview2XML().saveState(choice);
1550 } catch (OutOfMemoryError oom)
1552 new OOMWarning("Whilst saving current state to "
1553 + choice.getName(), oom);
1554 } catch (Exception ex)
1557 "Problems whilst trying to save to " + choice.getName(),
1559 JOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1560 "label.error_whilst_saving_current_state_to",
1561 new Object[] { choice.getName() }), MessageManager
1562 .getString("label.couldnt_save_project"),
1563 JOptionPane.WARNING_MESSAGE);
1565 setProgressBar(null, choice.hashCode());
1571 private void setProjectFile(File choice)
1573 this.projectFile = choice;
1576 public File getProjectFile()
1578 return this.projectFile;
1588 public void loadState_actionPerformed(ActionEvent e)
1590 JalviewFileChooser chooser = new JalviewFileChooser(
1591 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] {
1592 "jvp", "jar" }, new String[] { "Jalview Project",
1593 "Jalview Project (old)" }, "Jalview Project");
1594 chooser.setFileView(new JalviewFileView());
1595 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1597 int value = chooser.showOpenDialog(this);
1599 if (value == JalviewFileChooser.APPROVE_OPTION)
1601 final File selectedFile = chooser.getSelectedFile();
1602 setProjectFile(selectedFile);
1603 final String choice = selectedFile.getAbsolutePath();
1604 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1605 selectedFile.getParent());
1606 new Thread(new Runnable()
1612 MessageManager.formatMessage(
1613 "label.loading_jalview_project",
1614 new Object[] { choice }), choice.hashCode());
1617 new Jalview2XML().loadJalviewAlign(choice);
1618 } catch (OutOfMemoryError oom)
1620 new OOMWarning("Whilst loading project from " + choice, oom);
1621 } catch (Exception ex)
1623 Cache.log.error("Problems whilst loading project from "
1625 JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1627 "label.error_whilst_loading_project_from",
1628 new Object[] { choice }), MessageManager
1629 .getString("label.couldnt_load_project"),
1630 JOptionPane.WARNING_MESSAGE);
1632 setProgressBar(null, choice.hashCode());
1639 public void inputSequence_actionPerformed(ActionEvent e)
1641 new SequenceFetcher(this);
1644 JPanel progressPanel;
1646 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1648 public void startLoading(final String fileName)
1650 if (fileLoadingCount == 0)
1652 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1653 "label.loading_file", new Object[] { fileName })));
1658 private JPanel addProgressPanel(String string)
1660 if (progressPanel == null)
1662 progressPanel = new JPanel(new GridLayout(1, 1));
1663 totalProgressCount = 0;
1664 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1666 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1667 JProgressBar progressBar = new JProgressBar();
1668 progressBar.setIndeterminate(true);
1670 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1672 thisprogress.add(progressBar, BorderLayout.CENTER);
1673 progressPanel.add(thisprogress);
1674 ((GridLayout) progressPanel.getLayout())
1675 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1676 ++totalProgressCount;
1677 instance.validate();
1678 return thisprogress;
1681 int totalProgressCount = 0;
1683 private void removeProgressPanel(JPanel progbar)
1685 if (progressPanel != null)
1687 synchronized (progressPanel)
1689 progressPanel.remove(progbar);
1690 GridLayout gl = (GridLayout) progressPanel.getLayout();
1691 gl.setRows(gl.getRows() - 1);
1692 if (--totalProgressCount < 1)
1694 this.getContentPane().remove(progressPanel);
1695 progressPanel = null;
1702 public void stopLoading()
1705 if (fileLoadingCount < 1)
1707 while (fileLoadingPanels.size() > 0)
1709 removeProgressPanel(fileLoadingPanels.remove(0));
1711 fileLoadingPanels.clear();
1712 fileLoadingCount = 0;
1717 public static int getViewCount(String alignmentId)
1719 AlignmentViewport[] aps = getViewports(alignmentId);
1720 return (aps == null) ? 0 : aps.length;
1725 * @param alignmentId
1726 * - if null, all sets are returned
1727 * @return all AlignmentPanels concerning the alignmentId sequence set
1729 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1731 if (Desktop.desktop == null)
1733 // no frames created and in headless mode
1734 // TODO: verify that frames are recoverable when in headless mode
1737 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1738 AlignFrame[] frames = getAlignFrames();
1743 for (AlignFrame af : frames)
1745 for (AlignmentPanel ap : af.alignPanels)
1747 if (alignmentId == null
1748 || alignmentId.equals(ap.av.getSequenceSetId()))
1754 if (aps.size() == 0)
1758 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1763 * get all the viewports on an alignment.
1765 * @param sequenceSetId
1766 * unique alignment id (may be null - all viewports returned in that
1768 * @return all viewports on the alignment bound to sequenceSetId
1770 public static AlignmentViewport[] getViewports(String sequenceSetId)
1772 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1773 if (desktop != null)
1775 AlignFrame[] frames = Desktop.getAlignFrames();
1777 for (AlignFrame afr : frames)
1779 if (sequenceSetId == null
1780 || afr.getViewport().getSequenceSetId()
1781 .equals(sequenceSetId))
1783 if (afr.alignPanels != null)
1785 for (AlignmentPanel ap : afr.alignPanels)
1787 if (sequenceSetId == null
1788 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1796 viewp.add(afr.getViewport());
1800 if (viewp.size() > 0)
1802 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1809 * Explode the views in the given frame into separate AlignFrame
1813 public static void explodeViews(AlignFrame af)
1815 int size = af.alignPanels.size();
1821 for (int i = 0; i < size; i++)
1823 AlignmentPanel ap = af.alignPanels.get(i);
1824 AlignFrame newaf = new AlignFrame(ap);
1827 * Restore the view's last exploded frame geometry if known. Multiple
1828 * views from one exploded frame share and restore the same (frame)
1829 * position and size.
1831 Rectangle geometry = ap.av.getExplodedGeometry();
1832 if (geometry != null)
1834 newaf.setBounds(geometry);
1837 ap.av.setGatherViewsHere(false);
1839 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1840 AlignFrame.DEFAULT_HEIGHT);
1843 af.alignPanels.clear();
1844 af.closeMenuItem_actionPerformed(true);
1849 * Gather expanded views (separate AlignFrame's) with the same sequence set
1850 * identifier back in to this frame as additional views, and close the
1851 * expanded views. Note the expanded frames may themselves have multiple
1852 * views. We take the lot.
1856 public void gatherViews(AlignFrame source)
1858 source.viewport.setGatherViewsHere(true);
1859 source.viewport.setExplodedGeometry(source.getBounds());
1860 JInternalFrame[] frames = desktop.getAllFrames();
1861 String viewId = source.viewport.getSequenceSetId();
1863 for (int t = 0; t < frames.length; t++)
1865 if (frames[t] instanceof AlignFrame && frames[t] != source)
1867 AlignFrame af = (AlignFrame) frames[t];
1868 boolean gatherThis = false;
1869 for (int a = 0; a < af.alignPanels.size(); a++)
1871 AlignmentPanel ap = af.alignPanels.get(a);
1872 if (viewId.equals(ap.av.getSequenceSetId()))
1875 ap.av.setGatherViewsHere(false);
1876 ap.av.setExplodedGeometry(af.getBounds());
1877 source.addAlignmentPanel(ap, false);
1883 af.alignPanels.clear();
1884 af.closeMenuItem_actionPerformed(true);
1891 jalview.gui.VamsasApplication v_client = null;
1894 public void vamsasImport_actionPerformed(ActionEvent e)
1896 if (v_client == null)
1898 // Load and try to start a session.
1899 JalviewFileChooser chooser = new JalviewFileChooser(
1900 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1902 chooser.setFileView(new JalviewFileView());
1903 chooser.setDialogTitle(MessageManager
1904 .getString("label.open_saved_vamsas_session"));
1905 chooser.setToolTipText(MessageManager
1906 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1908 int value = chooser.showOpenDialog(this);
1910 if (value == JalviewFileChooser.APPROVE_OPTION)
1912 String fle = chooser.getSelectedFile().toString();
1913 if (!vamsasImport(chooser.getSelectedFile()))
1916 .showInternalMessageDialog(
1918 MessageManager.formatMessage(
1919 "label.couldnt_import_as_vamsas_session",
1920 new Object[] { fle }),
1922 .getString("label.vamsas_document_import_failed"),
1923 JOptionPane.ERROR_MESSAGE);
1929 jalview.bin.Cache.log
1930 .error("Implementation error - load session from a running session is not supported.");
1935 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1938 * @return true if import was a success and a session was started.
1940 public boolean vamsasImport(URL url)
1942 // TODO: create progress bar
1943 if (v_client != null)
1946 jalview.bin.Cache.log
1947 .error("Implementation error - load session from a running session is not supported.");
1953 // copy the URL content to a temporary local file
1954 // TODO: be a bit cleverer here with nio (?!)
1955 File file = File.createTempFile("vdocfromurl", ".vdj");
1956 FileOutputStream fos = new FileOutputStream(file);
1957 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1958 byte[] buffer = new byte[2048];
1960 while ((ln = bis.read(buffer)) > -1)
1962 fos.write(buffer, 0, ln);
1966 v_client = new jalview.gui.VamsasApplication(this, file,
1967 url.toExternalForm());
1968 } catch (Exception ex)
1970 jalview.bin.Cache.log.error(
1971 "Failed to create new vamsas session from contents of URL "
1975 setupVamsasConnectedGui();
1976 v_client.initial_update(); // TODO: thread ?
1977 return v_client.inSession();
1981 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1984 * @return true if import was a success and a session was started.
1986 public boolean vamsasImport(File file)
1988 if (v_client != null)
1991 jalview.bin.Cache.log
1992 .error("Implementation error - load session from a running session is not supported.");
1996 setProgressBar(MessageManager.formatMessage(
1997 "status.importing_vamsas_session_from",
1998 new Object[] { file.getName() }), file.hashCode());
2001 v_client = new jalview.gui.VamsasApplication(this, file, null);
2002 } catch (Exception ex)
2004 setProgressBar(MessageManager.formatMessage(
2005 "status.importing_vamsas_session_from",
2006 new Object[] { file.getName() }), file.hashCode());
2007 jalview.bin.Cache.log.error(
2008 "New vamsas session from existing session file failed:", ex);
2011 setupVamsasConnectedGui();
2012 v_client.initial_update(); // TODO: thread ?
2013 setProgressBar(MessageManager.formatMessage(
2014 "status.importing_vamsas_session_from",
2015 new Object[] { file.getName() }), file.hashCode());
2016 return v_client.inSession();
2019 public boolean joinVamsasSession(String mysesid)
2021 if (v_client != null)
2025 .getString("error.try_join_vamsas_session_another"));
2027 if (mysesid == null)
2030 MessageManager.getString("error.invalid_vamsas_session_id"));
2032 v_client = new VamsasApplication(this, mysesid);
2033 setupVamsasConnectedGui();
2034 v_client.initial_update();
2035 return (v_client.inSession());
2039 public void vamsasStart_actionPerformed(ActionEvent e)
2041 if (v_client == null)
2044 // we just start a default session for moment.
2046 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2047 * getProperty("LAST_DIRECTORY"));
2049 * chooser.setFileView(new JalviewFileView());
2050 * chooser.setDialogTitle("Load Vamsas file");
2051 * chooser.setToolTipText("Import");
2053 * int value = chooser.showOpenDialog(this);
2055 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2056 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2058 v_client = new VamsasApplication(this);
2059 setupVamsasConnectedGui();
2060 v_client.initial_update(); // TODO: thread ?
2064 // store current data in session.
2065 v_client.push_update(); // TODO: thread
2069 protected void setupVamsasConnectedGui()
2071 vamsasStart.setText(MessageManager.getString("label.session_update"));
2072 vamsasSave.setVisible(true);
2073 vamsasStop.setVisible(true);
2074 vamsasImport.setVisible(false); // Document import to existing session is
2075 // not possible for vamsas-client-1.0.
2078 protected void setupVamsasDisconnectedGui()
2080 vamsasSave.setVisible(false);
2081 vamsasStop.setVisible(false);
2082 vamsasImport.setVisible(true);
2083 vamsasStart.setText(MessageManager
2084 .getString("label.new_vamsas_session"));
2088 public void vamsasStop_actionPerformed(ActionEvent e)
2090 if (v_client != null)
2092 v_client.end_session();
2094 setupVamsasDisconnectedGui();
2098 protected void buildVamsasStMenu()
2100 if (v_client == null)
2102 String[] sess = null;
2105 sess = VamsasApplication.getSessionList();
2106 } catch (Exception e)
2108 jalview.bin.Cache.log.warn(
2109 "Problem getting current sessions list.", e);
2114 jalview.bin.Cache.log.debug("Got current sessions list: "
2115 + sess.length + " entries.");
2116 VamsasStMenu.removeAll();
2117 for (int i = 0; i < sess.length; i++)
2119 JMenuItem sessit = new JMenuItem();
2120 sessit.setText(sess[i]);
2121 sessit.setToolTipText(MessageManager.formatMessage(
2122 "label.connect_to_session", new Object[] { sess[i] }));
2123 final Desktop dsktp = this;
2124 final String mysesid = sess[i];
2125 sessit.addActionListener(new ActionListener()
2129 public void actionPerformed(ActionEvent e)
2131 if (dsktp.v_client == null)
2133 Thread rthr = new Thread(new Runnable()
2139 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2140 dsktp.setupVamsasConnectedGui();
2141 dsktp.v_client.initial_update();
2149 VamsasStMenu.add(sessit);
2151 // don't show an empty menu.
2152 VamsasStMenu.setVisible(sess.length > 0);
2157 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2158 VamsasStMenu.removeAll();
2159 VamsasStMenu.setVisible(false);
2164 // Not interested in the content. Just hide ourselves.
2165 VamsasStMenu.setVisible(false);
2170 public void vamsasSave_actionPerformed(ActionEvent e)
2172 if (v_client != null)
2174 JalviewFileChooser chooser = new JalviewFileChooser(
2175 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
2176 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2177 new String[] { "Vamsas Document" }, "Vamsas Document");
2179 chooser.setFileView(new JalviewFileView());
2180 chooser.setDialogTitle(MessageManager
2181 .getString("label.save_vamsas_document_archive"));
2183 int value = chooser.showSaveDialog(this);
2185 if (value == JalviewFileChooser.APPROVE_OPTION)
2187 java.io.File choice = chooser.getSelectedFile();
2188 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2189 "label.saving_vamsas_doc",
2190 new Object[] { choice.getName() }));
2191 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2192 String warnmsg = null;
2193 String warnttl = null;
2196 v_client.vclient.storeDocument(choice);
2199 warnttl = "Serious Problem saving Vamsas Document";
2200 warnmsg = ex.toString();
2201 jalview.bin.Cache.log.error("Error Whilst saving document to "
2204 } catch (Exception ex)
2206 warnttl = "Problem saving Vamsas Document.";
2207 warnmsg = ex.toString();
2208 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2212 removeProgressPanel(progpanel);
2213 if (warnmsg != null)
2215 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2217 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2223 JPanel vamUpdate = null;
2226 * hide vamsas user gui bits when a vamsas document event is being handled.
2229 * true to hide gui, false to reveal gui
2231 public void setVamsasUpdate(boolean b)
2233 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2234 + (b ? "in progress" : "finished"));
2236 if (vamUpdate != null)
2238 this.removeProgressPanel(vamUpdate);
2242 vamUpdate = this.addProgressPanel(MessageManager
2243 .getString("label.updating_vamsas_session"));
2245 vamsasStart.setVisible(!b);
2246 vamsasStop.setVisible(!b);
2247 vamsasSave.setVisible(!b);
2250 public JInternalFrame[] getAllFrames()
2252 return desktop.getAllFrames();
2256 * Checks the given url to see if it gives a response indicating that the user
2257 * should be informed of a new questionnaire.
2261 public void checkForQuestionnaire(String url)
2263 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2264 // javax.swing.SwingUtilities.invokeLater(jvq);
2265 new Thread(jvq).start();
2268 public void checkURLLinks()
2270 // Thread off the URL link checker
2271 addDialogThread(new Runnable()
2276 if (Cache.getDefault("CHECKURLLINKS", true))
2278 // check what the actual links are - if it's just the default don't
2279 // bother with the warning
2280 Vector<String> links = Preferences.sequenceUrlLinks
2281 .getLinksForDisplay();
2283 // only need to check links if there is one with a
2284 // SEQUENCE_ID which is not the default EMBL_EBI link
2285 ListIterator<String> li = links.listIterator();
2286 boolean check = false;
2287 List<JLabel> urls = new ArrayList<JLabel>();
2288 while (li.hasNext())
2290 String link = li.next();
2291 if (link.contains(SEQUENCE_ID)
2292 && !link.equals(UrlProviderI.DEFAULT_STRING))
2295 int barPos = link.indexOf("|");
2296 String urlMsg = barPos == -1 ? link : link.substring(0,
2297 barPos) + ": " + link.substring(barPos + 1);
2298 urls.add(new JLabel(urlMsg));
2306 // ask user to check in case URL links use old style tokens
2307 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2308 JPanel msgPanel = new JPanel();
2309 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2310 msgPanel.add(Box.createVerticalGlue());
2311 JLabel msg = new JLabel(
2313 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2314 JLabel msg2 = new JLabel(
2316 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2318 for (JLabel url : urls)
2324 final JCheckBox jcb = new JCheckBox(
2325 MessageManager.getString("label.do_not_display_again"));
2326 jcb.addActionListener(new ActionListener()
2329 public void actionPerformed(ActionEvent e)
2331 // update Cache settings for "don't show this again"
2332 boolean showWarningAgain = !jcb.isSelected();
2333 Cache.setProperty("CHECKURLLINKS",
2334 Boolean.valueOf(showWarningAgain).toString());
2339 JOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2341 .getString("label.SEQUENCE_ID_no_longer_used"),
2342 JOptionPane.WARNING_MESSAGE);
2349 * Proxy class for JDesktopPane which optionally displays the current memory
2350 * usage and highlights the desktop area with a red bar if free memory runs
2355 public class MyDesktopPane extends JDesktopPane implements Runnable
2358 private static final float ONE_MB = 1048576f;
2360 boolean showMemoryUsage = false;
2364 java.text.NumberFormat df;
2366 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2369 public MyDesktopPane(boolean showMemoryUsage)
2371 showMemoryUsage(showMemoryUsage);
2374 public void showMemoryUsage(boolean showMemory)
2376 this.showMemoryUsage = showMemory;
2379 Thread worker = new Thread(this);
2384 public boolean isShowMemoryUsage()
2386 return showMemoryUsage;
2392 df = java.text.NumberFormat.getNumberInstance();
2393 df.setMaximumFractionDigits(2);
2394 runtime = Runtime.getRuntime();
2396 while (showMemoryUsage)
2400 maxMemory = runtime.maxMemory() / ONE_MB;
2401 allocatedMemory = runtime.totalMemory() / ONE_MB;
2402 freeMemory = runtime.freeMemory() / ONE_MB;
2403 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2405 percentUsage = (totalFreeMemory / maxMemory) * 100;
2407 // if (percentUsage < 20)
2409 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2411 // instance.set.setBorder(border1);
2414 // sleep after showing usage
2416 } catch (Exception ex)
2418 ex.printStackTrace();
2424 public void paintComponent(Graphics g)
2426 if (showMemoryUsage && g != null && df != null)
2428 if (percentUsage < 20)
2430 g.setColor(Color.red);
2432 FontMetrics fm = g.getFontMetrics();
2435 g.drawString(MessageManager.formatMessage(
2436 "label.memory_stats",
2437 new Object[] { df.format(totalFreeMemory),
2438 df.format(maxMemory), df.format(percentUsage) }), 10,
2439 getHeight() - fm.getHeight());
2446 * fixes stacking order after a modal dialog to ensure windows that should be
2447 * on top actually are
2449 public void relayerWindows()
2454 protected JMenuItem groovyShell;
2457 * Accessor method to quickly get all the AlignmentFrames loaded.
2459 * @return an array of AlignFrame, or null if none found
2461 public static AlignFrame[] getAlignFrames()
2463 if (Jalview.isHeadlessMode())
2465 // Desktop.desktop is null in headless mode
2466 return new AlignFrame[] { Jalview.currentAlignFrame };
2469 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2475 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2477 for (int i = frames.length - 1; i > -1; i--)
2479 if (frames[i] instanceof AlignFrame)
2481 avp.add((AlignFrame) frames[i]);
2483 else if (frames[i] instanceof SplitFrame)
2486 * Also check for a split frame containing an AlignFrame
2488 GSplitFrame sf = (GSplitFrame) frames[i];
2489 if (sf.getTopFrame() instanceof AlignFrame)
2491 avp.add((AlignFrame) sf.getTopFrame());
2493 if (sf.getBottomFrame() instanceof AlignFrame)
2495 avp.add((AlignFrame) sf.getBottomFrame());
2499 if (avp.size() == 0)
2503 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2508 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2512 public GStructureViewer[] getJmols()
2514 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2520 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2522 for (int i = frames.length - 1; i > -1; i--)
2524 if (frames[i] instanceof AppJmol)
2526 GStructureViewer af = (GStructureViewer) frames[i];
2530 if (avp.size() == 0)
2534 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2539 * Add Groovy Support to Jalview
2541 public void groovyShell_actionPerformed()
2545 openGroovyConsole();
2546 } catch (Exception ex)
2548 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2549 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2551 MessageManager.getString("label.couldnt_create_groovy_shell"),
2552 MessageManager.getString("label.groovy_support_failed"),
2553 JOptionPane.ERROR_MESSAGE);
2558 * Open the Groovy console
2560 void openGroovyConsole()
2562 if (groovyConsole == null)
2564 groovyConsole = new groovy.ui.Console();
2565 groovyConsole.setVariable("Jalview", this);
2566 groovyConsole.run();
2569 * We allow only one console at a time, so that AlignFrame menu option
2570 * 'Calculate | Run Groovy script' is unambiguous.
2571 * Disable 'Groovy Console', and enable 'Run script', when the console is
2572 * opened, and the reverse when it is closed
2574 Window window = (Window) groovyConsole.getFrame();
2575 window.addWindowListener(new WindowAdapter()
2578 public void windowClosed(WindowEvent e)
2581 * rebind CMD-Q from Groovy Console to Jalview Quit
2584 enableExecuteGroovy(false);
2590 * show Groovy console window (after close and reopen)
2592 ((Window) groovyConsole.getFrame()).setVisible(true);
2595 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2596 * and disable opening a second console
2598 enableExecuteGroovy(true);
2602 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2603 * binding when opened
2605 protected void addQuitHandler()
2607 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2608 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2609 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2610 getRootPane().getActionMap().put("Quit", new AbstractAction()
2613 public void actionPerformed(ActionEvent e)
2621 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2624 * true if Groovy console is open
2626 public void enableExecuteGroovy(boolean enabled)
2629 * disable opening a second Groovy console
2630 * (or re-enable when the console is closed)
2632 groovyShell.setEnabled(!enabled);
2634 AlignFrame[] alignFrames = getAlignFrames();
2635 if (alignFrames != null)
2637 for (AlignFrame af : alignFrames)
2639 af.setGroovyEnabled(enabled);
2645 * Progress bars managed by the IProgressIndicator method.
2647 private Hashtable<Long, JPanel> progressBars;
2649 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2654 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2657 public void setProgressBar(String message, long id)
2659 if (progressBars == null)
2661 progressBars = new Hashtable<Long, JPanel>();
2662 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2665 if (progressBars.get(new Long(id)) != null)
2667 JPanel panel = progressBars.remove(new Long(id));
2668 if (progressBarHandlers.contains(new Long(id)))
2670 progressBarHandlers.remove(new Long(id));
2672 removeProgressPanel(panel);
2676 progressBars.put(new Long(id), addProgressPanel(message));
2683 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2684 * jalview.gui.IProgressIndicatorHandler)
2687 public void registerHandler(final long id,
2688 final IProgressIndicatorHandler handler)
2690 if (progressBarHandlers == null
2691 || !progressBars.containsKey(new Long(id)))
2695 .getString("error.call_setprogressbar_before_registering_handler"));
2697 progressBarHandlers.put(new Long(id), handler);
2698 final JPanel progressPanel = progressBars.get(new Long(id));
2699 if (handler.canCancel())
2701 JButton cancel = new JButton(
2702 MessageManager.getString("action.cancel"));
2703 final IProgressIndicator us = this;
2704 cancel.addActionListener(new ActionListener()
2708 public void actionPerformed(ActionEvent e)
2710 handler.cancelActivity(id);
2711 us.setProgressBar(MessageManager.formatMessage(
2712 "label.cancelled_params",
2713 new Object[] { ((JLabel) progressPanel.getComponent(0))
2717 progressPanel.add(cancel, BorderLayout.EAST);
2723 * @return true if any progress bars are still active
2726 public boolean operationInProgress()
2728 if (progressBars != null && progressBars.size() > 0)
2736 * This will return the first AlignFrame holding the given viewport instance.
2737 * It will break if there are more than one AlignFrames viewing a particular
2741 * @return alignFrame for viewport
2743 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2745 if (desktop != null)
2747 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2748 for (int panel = 0; aps != null && panel < aps.length; panel++)
2750 if (aps[panel] != null && aps[panel].av == viewport)
2752 return aps[panel].alignFrame;
2759 public VamsasApplication getVamsasApplication()
2766 * flag set if jalview GUI is being operated programmatically
2768 private boolean inBatchMode = false;
2771 * check if jalview GUI is being operated programmatically
2773 * @return inBatchMode
2775 public boolean isInBatchMode()
2781 * set flag if jalview GUI is being operated programmatically
2783 * @param inBatchMode
2785 public void setInBatchMode(boolean inBatchMode)
2787 this.inBatchMode = inBatchMode;
2790 public void startServiceDiscovery()
2792 startServiceDiscovery(false);
2795 public void startServiceDiscovery(boolean blocking)
2797 boolean alive = true;
2798 Thread t0 = null, t1 = null, t2 = null;
2799 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2802 // todo: changesupport handlers need to be transferred
2803 if (discoverer == null)
2805 discoverer = new jalview.ws.jws1.Discoverer();
2806 // register PCS handler for desktop.
2807 discoverer.addPropertyChangeListener(changeSupport);
2809 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2810 // until we phase out completely
2811 (t0 = new Thread(discoverer)).start();
2814 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2816 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2818 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2820 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2826 // TODO: do rest service discovery
2835 } catch (Exception e)
2838 alive = (t1 != null && t1.isAlive())
2839 || (t2 != null && t2.isAlive())
2840 || (t3 != null && t3.isAlive())
2841 || (t0 != null && t0.isAlive());
2847 * called to check if the service discovery process completed successfully.
2851 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2853 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2855 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2856 .getErrorMessages();
2859 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2861 if (serviceChangedDialog == null)
2863 // only run if we aren't already displaying one of these.
2864 addDialogThread(serviceChangedDialog = new Runnable()
2871 * JalviewDialog jd =new JalviewDialog() {
2873 * @Override protected void cancelPressed() { // TODO
2874 * Auto-generated method stub
2876 * }@Override protected void okPressed() { // TODO
2877 * Auto-generated method stub
2879 * }@Override protected void raiseClosed() { // TODO
2880 * Auto-generated method stub
2882 * } }; jd.initDialogFrame(new
2883 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2884 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2885 * + " or mis-configured HTTP proxy settings.<br/>" +
2886 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2888 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2889 * ), true, true, "Web Service Configuration Problem", 450,
2892 * jd.waitForInput();
2898 "<html><table width=\"450\"><tr><td>"
2900 + "</td></tr></table>"
2901 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2902 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2903 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2904 + " Tools->Preferences dialog box to change them.</p></html>"),
2905 "Web Service Configuration Problem",
2906 JOptionPane.DEFAULT_OPTION,
2907 JOptionPane.ERROR_MESSAGE);
2908 serviceChangedDialog = null;
2917 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2924 private Runnable serviceChangedDialog = null;
2927 * start a thread to open a URL in the configured browser. Pops up a warning
2928 * dialog to the user if there is an exception when calling out to the browser
2933 public static void showUrl(final String url)
2935 showUrl(url, Desktop.instance);
2939 * Like showUrl but allows progress handler to be specified
2943 * (null) or object implementing IProgressIndicator
2945 public static void showUrl(final String url,
2946 final IProgressIndicator progress)
2948 new Thread(new Runnable()
2955 if (progress != null)
2957 progress.setProgressBar(MessageManager.formatMessage(
2958 "status.opening_params", new Object[] { url }), this
2961 jalview.util.BrowserLauncher.openURL(url);
2962 } catch (Exception ex)
2964 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2966 .getString("label.web_browser_not_found_unix"),
2967 MessageManager.getString("label.web_browser_not_found"),
2968 JOptionPane.WARNING_MESSAGE);
2970 ex.printStackTrace();
2972 if (progress != null)
2974 progress.setProgressBar(null, this.hashCode());
2980 public static WsParamSetManager wsparamManager = null;
2982 public static ParamManager getUserParameterStore()
2984 if (wsparamManager == null)
2986 wsparamManager = new WsParamSetManager();
2988 return wsparamManager;
2992 * static hyperlink handler proxy method for use by Jalview's internal windows
2996 public static void hyperlinkUpdate(HyperlinkEvent e)
2998 if (e.getEventType() == EventType.ACTIVATED)
3003 url = e.getURL().toString();
3004 Desktop.showUrl(url);
3005 } catch (Exception x)
3009 if (Cache.log != null)
3011 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3015 System.err.println("Couldn't handle string " + url
3019 // ignore any exceptions due to dud links.
3026 * single thread that handles display of dialogs to user.
3028 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3031 * flag indicating if dialogExecutor should try to acquire a permit
3033 private volatile boolean dialogPause = true;
3038 private java.util.concurrent.Semaphore block = new Semaphore(0);
3040 private static groovy.ui.Console groovyConsole;
3043 * add another dialog thread to the queue
3047 public void addDialogThread(final Runnable prompter)
3049 dialogExecutor.submit(new Runnable()
3059 } catch (InterruptedException x)
3064 if (instance == null)
3070 SwingUtilities.invokeAndWait(prompter);
3071 } catch (Exception q)
3073 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3079 public void startDialogQueue()
3081 // set the flag so we don't pause waiting for another permit and semaphore
3082 // the current task to begin
3083 dialogPause = false;
3088 protected void snapShotWindow_actionPerformed(ActionEvent e)
3092 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3093 "View of Desktop", getWidth(), getHeight(), of = new File(
3094 "Jalview_snapshot" + System.currentTimeMillis()
3095 + ".eps"), "View of desktop", null, 0, false);
3098 paintAll(im.getGraphics());
3100 } catch (Exception q)
3102 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3106 Cache.log.info("Successfully written snapshot to file "
3107 + of.getAbsolutePath());
3111 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3112 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3113 * and location last time the view was expanded (if any). However it does not
3114 * remember the split pane divider location - this is set to match the
3115 * 'exploding' frame.
3119 public void explodeViews(SplitFrame sf)
3121 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3122 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3123 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3125 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3127 int viewCount = topPanels.size();
3134 * Processing in reverse order works, forwards order leaves the first panels
3135 * not visible. I don't know why!
3137 for (int i = viewCount - 1; i >= 0; i--)
3140 * Make new top and bottom frames. These take over the respective
3141 * AlignmentPanel objects, including their AlignmentViewports, so the
3142 * cdna/protein relationships between the viewports is carried over to the
3145 * explodedGeometry holds the (x, y) position of the previously exploded
3146 * SplitFrame, and the (width, height) of the AlignFrame component
3148 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3149 AlignFrame newTopFrame = new AlignFrame(topPanel);
3150 newTopFrame.setSize(oldTopFrame.getSize());
3151 newTopFrame.setVisible(true);
3152 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3153 .getExplodedGeometry();
3154 if (geometry != null)
3156 newTopFrame.setSize(geometry.getSize());
3159 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3160 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3161 newBottomFrame.setSize(oldBottomFrame.getSize());
3162 newBottomFrame.setVisible(true);
3163 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3164 .getExplodedGeometry();
3165 if (geometry != null)
3167 newBottomFrame.setSize(geometry.getSize());
3170 topPanel.av.setGatherViewsHere(false);
3171 bottomPanel.av.setGatherViewsHere(false);
3172 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3174 if (geometry != null)
3176 splitFrame.setLocation(geometry.getLocation());
3178 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3182 * Clear references to the panels (now relocated in the new SplitFrames)
3183 * before closing the old SplitFrame.
3186 bottomPanels.clear();
3191 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3192 * back into the given SplitFrame as additional views. Note that the gathered
3193 * frames may themselves have multiple views.
3197 public void gatherViews(GSplitFrame source)
3200 * special handling of explodedGeometry for a view within a SplitFrame: - it
3201 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3202 * height) of the AlignFrame component
3204 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3205 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3206 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3207 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3208 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3209 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3211 myTopFrame.viewport.setGatherViewsHere(true);
3212 myBottomFrame.viewport.setGatherViewsHere(true);
3213 String topViewId = myTopFrame.viewport.getSequenceSetId();
3214 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3216 JInternalFrame[] frames = desktop.getAllFrames();
3217 for (JInternalFrame frame : frames)
3219 if (frame instanceof SplitFrame && frame != source)
3221 SplitFrame sf = (SplitFrame) frame;
3222 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3223 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3224 boolean gatherThis = false;
3225 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3227 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3228 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3229 if (topViewId.equals(topPanel.av.getSequenceSetId())
3230 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3233 topPanel.av.setGatherViewsHere(false);
3234 bottomPanel.av.setGatherViewsHere(false);
3235 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3236 topFrame.getSize()));
3237 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3238 .getLocation(), bottomFrame.getSize()));
3239 myTopFrame.addAlignmentPanel(topPanel, false);
3240 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3246 topFrame.getAlignPanels().clear();
3247 bottomFrame.getAlignPanels().clear();
3254 * The dust settles...give focus to the tab we did this from.
3256 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3259 public static groovy.ui.Console getGroovyConsole()
3261 return groovyConsole;
3264 public static void transferFromDropTarget(List<String> files,
3265 List<String> protocols, DropTargetDropEvent evt, Transferable t)
3269 DataFlavor uriListFlavor = new DataFlavor(
3270 "text/uri-list;class=java.lang.String");
3271 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3273 // Works on Windows and MacOSX
3274 Cache.log.debug("Drop handled as javaFileListFlavor");
3275 for (Object file : (List) t
3276 .getTransferData(DataFlavor.javaFileListFlavor))
3278 files.add(((File) file).toString());
3279 protocols.add(FormatAdapter.FILE);
3284 // Unix like behaviour
3285 boolean added = false;
3287 if (t.isDataFlavorSupported(uriListFlavor))
3289 Cache.log.debug("Drop handled as uriListFlavor");
3290 // This is used by Unix drag system
3291 data = (String) t.getTransferData(uriListFlavor);
3295 // fallback to text: workaround - on OSX where there's a JVM bug
3296 Cache.log.debug("standard URIListFlavor failed. Trying text");
3297 // try text fallback
3298 data = (String) t.getTransferData(new DataFlavor(
3299 "text/plain;class=java.lang.String"));
3300 if (Cache.log.isDebugEnabled())
3302 Cache.log.debug("fallback returned " + data);
3305 while (protocols.size() < files.size())
3307 Cache.log.debug("Adding missing FILE protocol for "
3308 + files.get(protocols.size()));
3309 protocols.add(FormatAdapter.FILE);
3311 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3312 data, "\r\n"); st.hasMoreTokens();)
3315 String s = st.nextToken();
3316 if (s.startsWith("#"))
3318 // the line is a comment (as per the RFC 2483)
3321 java.net.URI uri = new java.net.URI(s);
3322 if (uri.getScheme().toLowerCase().startsWith("http"))
3324 protocols.add(FormatAdapter.URL);
3325 files.add(uri.toString());
3329 // otherwise preserve old behaviour: catch all for file objects
3330 java.io.File file = new java.io.File(uri);
3331 protocols.add(FormatAdapter.FILE);
3332 files.add(file.toString());
3335 if (Cache.log.isDebugEnabled())
3337 if (data == null || !added)
3340 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3341 for (DataFlavor fl : t.getTransferDataFlavors())
3343 Cache.log.debug("Supported transfer dataflavor: "
3345 Object df = t.getTransferData(fl);
3348 Cache.log.debug("Retrieves: " + df);
3352 Cache.log.debug("Retrieved nothing");