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.FileLoader;
31 import jalview.io.FormatAdapter;
32 import jalview.io.IdentifyFile;
33 import jalview.io.JalviewFileChooser;
34 import jalview.io.JalviewFileView;
35 import jalview.jbgui.GSplitFrame;
36 import jalview.jbgui.GStructureViewer;
37 import jalview.structure.StructureSelectionManager;
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;
2282 // only need to check links if there is one with a
2283 // SEQUENCE_ID which is not the default EMBL_EBI link
2284 ListIterator<String> li = links.listIterator();
2285 boolean check = false;
2286 List<JLabel> urls = new ArrayList<JLabel>();
2287 while (li.hasNext())
2289 String link = li.next();
2290 if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
2293 int barPos = link.indexOf("|");
2294 String urlMsg = barPos == -1 ? link : link.substring(0,
2295 barPos) + ": " + link.substring(barPos + 1);
2296 urls.add(new JLabel(urlMsg));
2304 // ask user to check in case URL links use old style tokens
2305 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2306 JPanel msgPanel = new JPanel();
2307 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2308 msgPanel.add(Box.createVerticalGlue());
2309 JLabel msg = new JLabel(
2311 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2312 JLabel msg2 = new JLabel(
2314 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2316 for (JLabel url : urls)
2322 final JCheckBox jcb = new JCheckBox(
2323 MessageManager.getString("label.do_not_display_again"));
2324 jcb.addActionListener(new ActionListener()
2327 public void actionPerformed(ActionEvent e)
2329 // update Cache settings for "don't show this again"
2330 boolean showWarningAgain = !jcb.isSelected();
2331 Cache.setProperty("CHECKURLLINKS",
2332 Boolean.valueOf(showWarningAgain).toString());
2337 JOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2339 .getString("label.SEQUENCE_ID_no_longer_used"),
2340 JOptionPane.WARNING_MESSAGE);
2347 * Proxy class for JDesktopPane which optionally displays the current memory
2348 * usage and highlights the desktop area with a red bar if free memory runs
2353 public class MyDesktopPane extends JDesktopPane implements Runnable
2356 private static final float ONE_MB = 1048576f;
2358 boolean showMemoryUsage = false;
2362 java.text.NumberFormat df;
2364 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2367 public MyDesktopPane(boolean showMemoryUsage)
2369 showMemoryUsage(showMemoryUsage);
2372 public void showMemoryUsage(boolean showMemory)
2374 this.showMemoryUsage = showMemory;
2377 Thread worker = new Thread(this);
2382 public boolean isShowMemoryUsage()
2384 return showMemoryUsage;
2390 df = java.text.NumberFormat.getNumberInstance();
2391 df.setMaximumFractionDigits(2);
2392 runtime = Runtime.getRuntime();
2394 while (showMemoryUsage)
2398 maxMemory = runtime.maxMemory() / ONE_MB;
2399 allocatedMemory = runtime.totalMemory() / ONE_MB;
2400 freeMemory = runtime.freeMemory() / ONE_MB;
2401 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2403 percentUsage = (totalFreeMemory / maxMemory) * 100;
2405 // if (percentUsage < 20)
2407 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2409 // instance.set.setBorder(border1);
2412 // sleep after showing usage
2414 } catch (Exception ex)
2416 ex.printStackTrace();
2422 public void paintComponent(Graphics g)
2424 if (showMemoryUsage && g != null && df != null)
2426 if (percentUsage < 20)
2428 g.setColor(Color.red);
2430 FontMetrics fm = g.getFontMetrics();
2433 g.drawString(MessageManager.formatMessage(
2434 "label.memory_stats",
2435 new Object[] { df.format(totalFreeMemory),
2436 df.format(maxMemory), df.format(percentUsage) }), 10,
2437 getHeight() - fm.getHeight());
2444 * fixes stacking order after a modal dialog to ensure windows that should be
2445 * on top actually are
2447 public void relayerWindows()
2452 protected JMenuItem groovyShell;
2455 * Accessor method to quickly get all the AlignmentFrames loaded.
2457 * @return an array of AlignFrame, or null if none found
2459 public static AlignFrame[] getAlignFrames()
2461 if (Jalview.isHeadlessMode())
2463 // Desktop.desktop is null in headless mode
2464 return new AlignFrame[] { Jalview.currentAlignFrame };
2467 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2473 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2475 for (int i = frames.length - 1; i > -1; i--)
2477 if (frames[i] instanceof AlignFrame)
2479 avp.add((AlignFrame) frames[i]);
2481 else if (frames[i] instanceof SplitFrame)
2484 * Also check for a split frame containing an AlignFrame
2486 GSplitFrame sf = (GSplitFrame) frames[i];
2487 if (sf.getTopFrame() instanceof AlignFrame)
2489 avp.add((AlignFrame) sf.getTopFrame());
2491 if (sf.getBottomFrame() instanceof AlignFrame)
2493 avp.add((AlignFrame) sf.getBottomFrame());
2497 if (avp.size() == 0)
2501 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2506 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2510 public GStructureViewer[] getJmols()
2512 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2518 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2520 for (int i = frames.length - 1; i > -1; i--)
2522 if (frames[i] instanceof AppJmol)
2524 GStructureViewer af = (GStructureViewer) frames[i];
2528 if (avp.size() == 0)
2532 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2537 * Add Groovy Support to Jalview
2539 public void groovyShell_actionPerformed()
2543 openGroovyConsole();
2544 } catch (Exception ex)
2546 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2547 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2549 MessageManager.getString("label.couldnt_create_groovy_shell"),
2550 MessageManager.getString("label.groovy_support_failed"),
2551 JOptionPane.ERROR_MESSAGE);
2556 * Open the Groovy console
2558 void openGroovyConsole()
2560 if (groovyConsole == null)
2562 groovyConsole = new groovy.ui.Console();
2563 groovyConsole.setVariable("Jalview", this);
2564 groovyConsole.run();
2567 * We allow only one console at a time, so that AlignFrame menu option
2568 * 'Calculate | Run Groovy script' is unambiguous.
2569 * Disable 'Groovy Console', and enable 'Run script', when the console is
2570 * opened, and the reverse when it is closed
2572 Window window = (Window) groovyConsole.getFrame();
2573 window.addWindowListener(new WindowAdapter()
2576 public void windowClosed(WindowEvent e)
2579 * rebind CMD-Q from Groovy Console to Jalview Quit
2582 enableExecuteGroovy(false);
2588 * show Groovy console window (after close and reopen)
2590 ((Window) groovyConsole.getFrame()).setVisible(true);
2593 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2594 * and disable opening a second console
2596 enableExecuteGroovy(true);
2600 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2601 * binding when opened
2603 protected void addQuitHandler()
2605 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2606 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2607 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2608 getRootPane().getActionMap().put("Quit", new AbstractAction()
2611 public void actionPerformed(ActionEvent e)
2619 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2622 * true if Groovy console is open
2624 public void enableExecuteGroovy(boolean enabled)
2627 * disable opening a second Groovy console
2628 * (or re-enable when the console is closed)
2630 groovyShell.setEnabled(!enabled);
2632 AlignFrame[] alignFrames = getAlignFrames();
2633 if (alignFrames != null)
2635 for (AlignFrame af : alignFrames)
2637 af.setGroovyEnabled(enabled);
2643 * Progress bars managed by the IProgressIndicator method.
2645 private Hashtable<Long, JPanel> progressBars;
2647 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2652 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2655 public void setProgressBar(String message, long id)
2657 if (progressBars == null)
2659 progressBars = new Hashtable<Long, JPanel>();
2660 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2663 if (progressBars.get(new Long(id)) != null)
2665 JPanel panel = progressBars.remove(new Long(id));
2666 if (progressBarHandlers.contains(new Long(id)))
2668 progressBarHandlers.remove(new Long(id));
2670 removeProgressPanel(panel);
2674 progressBars.put(new Long(id), addProgressPanel(message));
2681 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2682 * jalview.gui.IProgressIndicatorHandler)
2685 public void registerHandler(final long id,
2686 final IProgressIndicatorHandler handler)
2688 if (progressBarHandlers == null
2689 || !progressBars.containsKey(new Long(id)))
2693 .getString("error.call_setprogressbar_before_registering_handler"));
2695 progressBarHandlers.put(new Long(id), handler);
2696 final JPanel progressPanel = progressBars.get(new Long(id));
2697 if (handler.canCancel())
2699 JButton cancel = new JButton(
2700 MessageManager.getString("action.cancel"));
2701 final IProgressIndicator us = this;
2702 cancel.addActionListener(new ActionListener()
2706 public void actionPerformed(ActionEvent e)
2708 handler.cancelActivity(id);
2709 us.setProgressBar(MessageManager.formatMessage(
2710 "label.cancelled_params",
2711 new Object[] { ((JLabel) progressPanel.getComponent(0))
2715 progressPanel.add(cancel, BorderLayout.EAST);
2721 * @return true if any progress bars are still active
2724 public boolean operationInProgress()
2726 if (progressBars != null && progressBars.size() > 0)
2734 * This will return the first AlignFrame holding the given viewport instance.
2735 * It will break if there are more than one AlignFrames viewing a particular
2739 * @return alignFrame for viewport
2741 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2743 if (desktop != null)
2745 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2746 for (int panel = 0; aps != null && panel < aps.length; panel++)
2748 if (aps[panel] != null && aps[panel].av == viewport)
2750 return aps[panel].alignFrame;
2757 public VamsasApplication getVamsasApplication()
2764 * flag set if jalview GUI is being operated programmatically
2766 private boolean inBatchMode = false;
2769 * check if jalview GUI is being operated programmatically
2771 * @return inBatchMode
2773 public boolean isInBatchMode()
2779 * set flag if jalview GUI is being operated programmatically
2781 * @param inBatchMode
2783 public void setInBatchMode(boolean inBatchMode)
2785 this.inBatchMode = inBatchMode;
2788 public void startServiceDiscovery()
2790 startServiceDiscovery(false);
2793 public void startServiceDiscovery(boolean blocking)
2795 boolean alive = true;
2796 Thread t0 = null, t1 = null, t2 = null;
2797 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2800 // todo: changesupport handlers need to be transferred
2801 if (discoverer == null)
2803 discoverer = new jalview.ws.jws1.Discoverer();
2804 // register PCS handler for desktop.
2805 discoverer.addPropertyChangeListener(changeSupport);
2807 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2808 // until we phase out completely
2809 (t0 = new Thread(discoverer)).start();
2812 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2814 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2816 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2818 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2824 // TODO: do rest service discovery
2833 } catch (Exception e)
2836 alive = (t1 != null && t1.isAlive())
2837 || (t2 != null && t2.isAlive())
2838 || (t3 != null && t3.isAlive())
2839 || (t0 != null && t0.isAlive());
2845 * called to check if the service discovery process completed successfully.
2849 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2851 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2853 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2854 .getErrorMessages();
2857 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2859 if (serviceChangedDialog == null)
2861 // only run if we aren't already displaying one of these.
2862 addDialogThread(serviceChangedDialog = new Runnable()
2869 * JalviewDialog jd =new JalviewDialog() {
2871 * @Override protected void cancelPressed() { // TODO
2872 * Auto-generated method stub
2874 * }@Override protected void okPressed() { // TODO
2875 * Auto-generated method stub
2877 * }@Override protected void raiseClosed() { // TODO
2878 * Auto-generated method stub
2880 * } }; jd.initDialogFrame(new
2881 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2882 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2883 * + " or mis-configured HTTP proxy settings.<br/>" +
2884 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2886 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2887 * ), true, true, "Web Service Configuration Problem", 450,
2890 * jd.waitForInput();
2896 "<html><table width=\"450\"><tr><td>"
2898 + "</td></tr></table>"
2899 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2900 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2901 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2902 + " Tools->Preferences dialog box to change them.</p></html>"),
2903 "Web Service Configuration Problem",
2904 JOptionPane.DEFAULT_OPTION,
2905 JOptionPane.ERROR_MESSAGE);
2906 serviceChangedDialog = null;
2915 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2922 private Runnable serviceChangedDialog = null;
2925 * start a thread to open a URL in the configured browser. Pops up a warning
2926 * dialog to the user if there is an exception when calling out to the browser
2931 public static void showUrl(final String url)
2933 showUrl(url, Desktop.instance);
2937 * Like showUrl but allows progress handler to be specified
2941 * (null) or object implementing IProgressIndicator
2943 public static void showUrl(final String url,
2944 final IProgressIndicator progress)
2946 new Thread(new Runnable()
2953 if (progress != null)
2955 progress.setProgressBar(MessageManager.formatMessage(
2956 "status.opening_params", new Object[] { url }), this
2959 jalview.util.BrowserLauncher.openURL(url);
2960 } catch (Exception ex)
2962 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2964 .getString("label.web_browser_not_found_unix"),
2965 MessageManager.getString("label.web_browser_not_found"),
2966 JOptionPane.WARNING_MESSAGE);
2968 ex.printStackTrace();
2970 if (progress != null)
2972 progress.setProgressBar(null, this.hashCode());
2978 public static WsParamSetManager wsparamManager = null;
2980 public static ParamManager getUserParameterStore()
2982 if (wsparamManager == null)
2984 wsparamManager = new WsParamSetManager();
2986 return wsparamManager;
2990 * static hyperlink handler proxy method for use by Jalview's internal windows
2994 public static void hyperlinkUpdate(HyperlinkEvent e)
2996 if (e.getEventType() == EventType.ACTIVATED)
3001 url = e.getURL().toString();
3002 Desktop.showUrl(url);
3003 } catch (Exception x)
3007 if (Cache.log != null)
3009 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3013 System.err.println("Couldn't handle string " + url
3017 // ignore any exceptions due to dud links.
3024 * single thread that handles display of dialogs to user.
3026 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3029 * flag indicating if dialogExecutor should try to acquire a permit
3031 private volatile boolean dialogPause = true;
3036 private java.util.concurrent.Semaphore block = new Semaphore(0);
3038 private static groovy.ui.Console groovyConsole;
3041 * add another dialog thread to the queue
3045 public void addDialogThread(final Runnable prompter)
3047 dialogExecutor.submit(new Runnable()
3057 } catch (InterruptedException x)
3062 if (instance == null)
3068 SwingUtilities.invokeAndWait(prompter);
3069 } catch (Exception q)
3071 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3077 public void startDialogQueue()
3079 // set the flag so we don't pause waiting for another permit and semaphore
3080 // the current task to begin
3081 dialogPause = false;
3086 protected void snapShotWindow_actionPerformed(ActionEvent e)
3090 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3091 "View of Desktop", getWidth(), getHeight(), of = new File(
3092 "Jalview_snapshot" + System.currentTimeMillis()
3093 + ".eps"), "View of desktop", null, 0, false);
3096 paintAll(im.getGraphics());
3098 } catch (Exception q)
3100 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3104 Cache.log.info("Successfully written snapshot to file "
3105 + of.getAbsolutePath());
3109 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3110 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3111 * and location last time the view was expanded (if any). However it does not
3112 * remember the split pane divider location - this is set to match the
3113 * 'exploding' frame.
3117 public void explodeViews(SplitFrame sf)
3119 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3120 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3121 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3123 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3125 int viewCount = topPanels.size();
3132 * Processing in reverse order works, forwards order leaves the first panels
3133 * not visible. I don't know why!
3135 for (int i = viewCount - 1; i >= 0; i--)
3138 * Make new top and bottom frames. These take over the respective
3139 * AlignmentPanel objects, including their AlignmentViewports, so the
3140 * cdna/protein relationships between the viewports is carried over to the
3143 * explodedGeometry holds the (x, y) position of the previously exploded
3144 * SplitFrame, and the (width, height) of the AlignFrame component
3146 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3147 AlignFrame newTopFrame = new AlignFrame(topPanel);
3148 newTopFrame.setSize(oldTopFrame.getSize());
3149 newTopFrame.setVisible(true);
3150 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3151 .getExplodedGeometry();
3152 if (geometry != null)
3154 newTopFrame.setSize(geometry.getSize());
3157 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3158 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3159 newBottomFrame.setSize(oldBottomFrame.getSize());
3160 newBottomFrame.setVisible(true);
3161 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3162 .getExplodedGeometry();
3163 if (geometry != null)
3165 newBottomFrame.setSize(geometry.getSize());
3168 topPanel.av.setGatherViewsHere(false);
3169 bottomPanel.av.setGatherViewsHere(false);
3170 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3172 if (geometry != null)
3174 splitFrame.setLocation(geometry.getLocation());
3176 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3180 * Clear references to the panels (now relocated in the new SplitFrames)
3181 * before closing the old SplitFrame.
3184 bottomPanels.clear();
3189 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3190 * back into the given SplitFrame as additional views. Note that the gathered
3191 * frames may themselves have multiple views.
3195 public void gatherViews(GSplitFrame source)
3198 * special handling of explodedGeometry for a view within a SplitFrame: - it
3199 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3200 * height) of the AlignFrame component
3202 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3203 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3204 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3205 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3206 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3207 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3209 myTopFrame.viewport.setGatherViewsHere(true);
3210 myBottomFrame.viewport.setGatherViewsHere(true);
3211 String topViewId = myTopFrame.viewport.getSequenceSetId();
3212 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3214 JInternalFrame[] frames = desktop.getAllFrames();
3215 for (JInternalFrame frame : frames)
3217 if (frame instanceof SplitFrame && frame != source)
3219 SplitFrame sf = (SplitFrame) frame;
3220 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3221 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3222 boolean gatherThis = false;
3223 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3225 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3226 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3227 if (topViewId.equals(topPanel.av.getSequenceSetId())
3228 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3231 topPanel.av.setGatherViewsHere(false);
3232 bottomPanel.av.setGatherViewsHere(false);
3233 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3234 topFrame.getSize()));
3235 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3236 .getLocation(), bottomFrame.getSize()));
3237 myTopFrame.addAlignmentPanel(topPanel, false);
3238 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3244 topFrame.getAlignPanels().clear();
3245 bottomFrame.getAlignPanels().clear();
3252 * The dust settles...give focus to the tab we did this from.
3254 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3257 public static groovy.ui.Console getGroovyConsole()
3259 return groovyConsole;
3262 public static void transferFromDropTarget(List<String> files,
3263 List<String> protocols, DropTargetDropEvent evt, Transferable t)
3267 DataFlavor uriListFlavor = new DataFlavor(
3268 "text/uri-list;class=java.lang.String");
3269 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3271 // Works on Windows and MacOSX
3272 Cache.log.debug("Drop handled as javaFileListFlavor");
3273 for (Object file : (List) t
3274 .getTransferData(DataFlavor.javaFileListFlavor))
3276 files.add(((File) file).toString());
3277 protocols.add(FormatAdapter.FILE);
3282 // Unix like behaviour
3283 boolean added = false;
3285 if (t.isDataFlavorSupported(uriListFlavor))
3287 Cache.log.debug("Drop handled as uriListFlavor");
3288 // This is used by Unix drag system
3289 data = (String) t.getTransferData(uriListFlavor);
3293 // fallback to text: workaround - on OSX where there's a JVM bug
3294 Cache.log.debug("standard URIListFlavor failed. Trying text");
3295 // try text fallback
3296 data = (String) t.getTransferData(new DataFlavor(
3297 "text/plain;class=java.lang.String"));
3298 if (Cache.log.isDebugEnabled())
3300 Cache.log.debug("fallback returned " + data);
3303 while (protocols.size() < files.size())
3305 Cache.log.debug("Adding missing FILE protocol for "
3306 + files.get(protocols.size()));
3307 protocols.add(FormatAdapter.FILE);
3309 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3310 data, "\r\n"); st.hasMoreTokens();)
3313 String s = st.nextToken();
3314 if (s.startsWith("#"))
3316 // the line is a comment (as per the RFC 2483)
3319 java.net.URI uri = new java.net.URI(s);
3320 if (uri.getScheme().toLowerCase().startsWith("http"))
3322 protocols.add(FormatAdapter.URL);
3323 files.add(uri.toString());
3327 // otherwise preserve old behaviour: catch all for file objects
3328 java.io.File file = new java.io.File(uri);
3329 protocols.add(FormatAdapter.FILE);
3330 files.add(file.toString());
3333 if (Cache.log.isDebugEnabled())
3335 if (data == null || !added)
3338 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3339 for (DataFlavor fl : t.getTransferDataFlavors())
3341 Cache.log.debug("Supported transfer dataflavor: "
3343 Object df = t.getTransferData(fl);
3346 Cache.log.debug("Retrieves: " + df);
3350 Cache.log.debug("Retrieved nothing");