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 jalview.api.AlignViewportI;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.bin.Cache;
26 import jalview.bin.Jalview;
27 import jalview.io.FileLoader;
28 import jalview.io.FormatAdapter;
29 import jalview.io.IdentifyFile;
30 import jalview.io.JalviewFileChooser;
31 import jalview.io.JalviewFileView;
32 import jalview.jbgui.GSplitFrame;
33 import jalview.jbgui.GStructureViewer;
34 import jalview.structure.StructureSelectionManager;
35 import jalview.util.ImageMaker;
36 import jalview.util.MessageManager;
37 import jalview.util.Platform;
38 import jalview.viewmodel.AlignmentViewport;
39 import jalview.ws.params.ParamManager;
41 import java.awt.BorderLayout;
42 import java.awt.Color;
43 import java.awt.Dimension;
44 import java.awt.FontMetrics;
45 import java.awt.Graphics;
46 import java.awt.GridLayout;
47 import java.awt.Point;
48 import java.awt.Rectangle;
49 import java.awt.Toolkit;
50 import java.awt.Window;
51 import java.awt.datatransfer.Clipboard;
52 import java.awt.datatransfer.ClipboardOwner;
53 import java.awt.datatransfer.DataFlavor;
54 import java.awt.datatransfer.Transferable;
55 import java.awt.dnd.DnDConstants;
56 import java.awt.dnd.DropTargetDragEvent;
57 import java.awt.dnd.DropTargetDropEvent;
58 import java.awt.dnd.DropTargetEvent;
59 import java.awt.dnd.DropTargetListener;
60 import java.awt.event.ActionEvent;
61 import java.awt.event.ActionListener;
62 import java.awt.event.FocusEvent;
63 import java.awt.event.FocusListener;
64 import java.awt.event.KeyEvent;
65 import java.awt.event.MouseAdapter;
66 import java.awt.event.MouseEvent;
67 import java.awt.event.WindowAdapter;
68 import java.awt.event.WindowEvent;
69 import java.beans.PropertyChangeEvent;
70 import java.beans.PropertyChangeListener;
71 import java.io.BufferedInputStream;
73 import java.io.FileOutputStream;
75 import java.util.ArrayList;
76 import java.util.Hashtable;
77 import java.util.List;
78 import java.util.StringTokenizer;
79 import java.util.Vector;
80 import java.util.concurrent.ExecutorService;
81 import java.util.concurrent.Executors;
82 import java.util.concurrent.Semaphore;
84 import javax.swing.AbstractAction;
85 import javax.swing.Box;
86 import javax.swing.BoxLayout;
87 import javax.swing.DefaultDesktopManager;
88 import javax.swing.DesktopManager;
89 import javax.swing.JButton;
90 import javax.swing.JCheckBox;
91 import javax.swing.JComboBox;
92 import javax.swing.JComponent;
93 import javax.swing.JDesktopPane;
94 import javax.swing.JFrame;
95 import javax.swing.JInternalFrame;
96 import javax.swing.JLabel;
97 import javax.swing.JMenuItem;
98 import javax.swing.JOptionPane;
99 import javax.swing.JPanel;
100 import javax.swing.JPopupMenu;
101 import javax.swing.JProgressBar;
102 import javax.swing.KeyStroke;
103 import javax.swing.SwingUtilities;
104 import javax.swing.event.HyperlinkEvent;
105 import javax.swing.event.HyperlinkEvent.EventType;
106 import javax.swing.event.InternalFrameAdapter;
107 import javax.swing.event.InternalFrameEvent;
108 import javax.swing.event.MenuEvent;
109 import javax.swing.event.MenuListener;
116 * @version $Revision: 1.155 $
118 public class Desktop extends jalview.jbgui.GDesktop implements
119 DropTargetListener, ClipboardOwner, IProgressIndicator,
120 jalview.api.StructureSelectionManagerProvider
123 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
126 * news reader - null if it was never started.
128 private BlogReader jvnews = null;
130 private File projectFile;
134 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
136 public void addJalviewPropertyChangeListener(
137 PropertyChangeListener listener)
139 changeSupport.addJalviewPropertyChangeListener(listener);
143 * @param propertyName
145 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
146 * java.beans.PropertyChangeListener)
148 public void addJalviewPropertyChangeListener(String propertyName,
149 PropertyChangeListener listener)
151 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
155 * @param propertyName
157 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
158 * java.beans.PropertyChangeListener)
160 public void removeJalviewPropertyChangeListener(String propertyName,
161 PropertyChangeListener listener)
163 changeSupport.removeJalviewPropertyChangeListener(propertyName,
167 /** Singleton Desktop instance */
168 public static Desktop instance;
170 public static MyDesktopPane desktop;
172 static int openFrameCount = 0;
174 static final int xOffset = 30;
176 static final int yOffset = 30;
178 public static jalview.ws.jws1.Discoverer discoverer;
180 public static Object[] jalviewClipboard;
182 public static boolean internalCopy = false;
184 static int fileLoadingCount = 0;
186 class MyDesktopManager implements DesktopManager
189 private DesktopManager delegate;
191 public MyDesktopManager(DesktopManager delegate)
193 this.delegate = delegate;
197 public void activateFrame(JInternalFrame f)
201 delegate.activateFrame(f);
202 } catch (NullPointerException npe)
204 Point p = getMousePosition();
205 instance.showPasteMenu(p.x, p.y);
210 public void beginDraggingFrame(JComponent f)
212 delegate.beginDraggingFrame(f);
216 public void beginResizingFrame(JComponent f, int direction)
218 delegate.beginResizingFrame(f, direction);
222 public void closeFrame(JInternalFrame f)
224 delegate.closeFrame(f);
228 public void deactivateFrame(JInternalFrame f)
230 delegate.deactivateFrame(f);
234 public void deiconifyFrame(JInternalFrame f)
236 delegate.deiconifyFrame(f);
240 public void dragFrame(JComponent f, int newX, int newY)
246 delegate.dragFrame(f, newX, newY);
250 public void endDraggingFrame(JComponent f)
252 delegate.endDraggingFrame(f);
256 public void endResizingFrame(JComponent f)
258 delegate.endResizingFrame(f);
262 public void iconifyFrame(JInternalFrame f)
264 delegate.iconifyFrame(f);
268 public void maximizeFrame(JInternalFrame f)
270 delegate.maximizeFrame(f);
274 public void minimizeFrame(JInternalFrame f)
276 delegate.minimizeFrame(f);
280 public void openFrame(JInternalFrame f)
282 delegate.openFrame(f);
286 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
293 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
297 public void setBoundsForFrame(JComponent f, int newX, int newY,
298 int newWidth, int newHeight)
300 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
303 // All other methods, simply delegate
308 * Creates a new Desktop object.
313 * A note to implementors. It is ESSENTIAL that any activities that might
314 * block are spawned off as threads rather than waited for during this
318 doVamsasClientCheck();
320 groovyShell = new JMenuItem();
321 groovyShell.setText(MessageManager.getString("label.groovy_console"));
322 groovyShell.addActionListener(new ActionListener()
325 public void actionPerformed(ActionEvent e)
327 groovyShell_actionPerformed();
330 toolsMenu.add(groovyShell);
331 groovyShell.setVisible(true);
333 doConfigureStructurePrefs();
334 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
335 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
336 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
338 boolean showjconsole = jalview.bin.Cache.getDefault(
339 "SHOW_JAVA_CONSOLE", false);
340 desktop = new MyDesktopPane(selmemusage);
341 if (Platform.isAMac())
343 desktop.setDoubleBuffered(false);
345 showMemusage.setSelected(selmemusage);
346 desktop.setBackground(Color.white);
347 getContentPane().setLayout(new BorderLayout());
348 // alternate config - have scrollbars - see notes in JAL-153
349 // JScrollPane sp = new JScrollPane();
350 // sp.getViewport().setView(desktop);
351 // getContentPane().add(sp, BorderLayout.CENTER);
352 getContentPane().add(desktop, BorderLayout.CENTER);
353 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
355 // This line prevents Windows Look&Feel resizing all new windows to maximum
356 // if previous window was maximised
357 desktop.setDesktopManager(new MyDesktopManager(
358 new DefaultDesktopManager()));
360 Rectangle dims = getLastKnownDimensions("");
367 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
368 setBounds((screenSize.width - 900) / 2,
369 (screenSize.height - 650) / 2, 900, 650);
371 jconsole = new Console(this, showjconsole);
372 // add essential build information
373 jconsole.setHeader("Jalview Version: "
374 + jalview.bin.Cache.getProperty("VERSION") + "\n"
375 + "Jalview Installation: "
376 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
377 + "\n" + "Build Date: "
378 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
379 + "Java version: " + System.getProperty("java.version") + "\n"
380 + System.getProperty("os.arch") + " "
381 + System.getProperty("os.name") + " "
382 + System.getProperty("os.version"));
384 showConsole(showjconsole);
386 showNews.setVisible(false);
390 this.addWindowListener(new WindowAdapter()
393 public void windowClosing(WindowEvent evt)
400 this.addMouseListener(ma = new MouseAdapter()
403 public void mousePressed(MouseEvent evt)
405 if (evt.isPopupTrigger()) // Mac
407 showPasteMenu(evt.getX(), evt.getY());
412 public void mouseReleased(MouseEvent evt)
414 if (evt.isPopupTrigger()) // Windows
416 showPasteMenu(evt.getX(), evt.getY());
420 desktop.addMouseListener(ma);
422 this.addFocusListener(new FocusListener()
426 public void focusLost(FocusEvent e)
428 // TODO Auto-generated method stub
433 public void focusGained(FocusEvent e)
435 Cache.log.debug("Relaying windows after focus gain");
436 // make sure that we sort windows properly after we gain focus
437 instance.relayerWindows();
440 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
441 // Spawn a thread that shows the splashscreen
442 SwingUtilities.invokeLater(new Runnable()
452 // Thread off a new instance of the file chooser - this reduces the time it
453 // takes to open it later on.
454 new Thread(new Runnable()
459 Cache.log.debug("Filechooser init thread started.");
460 new JalviewFileChooser(
461 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
462 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
463 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
464 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
465 Cache.log.debug("Filechooser init thread finished.");
468 // Add the service change listener
469 changeSupport.addJalviewPropertyChangeListener("services",
470 new PropertyChangeListener()
474 public void propertyChange(PropertyChangeEvent evt)
476 Cache.log.debug("Firing service changed event for "
477 + evt.getNewValue());
478 JalviewServicesChanged(evt);
484 public void doConfigureStructurePrefs()
486 // configure services
487 StructureSelectionManager ssm = StructureSelectionManager
488 .getStructureSelectionManager(this);
489 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
491 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
492 Preferences.ADD_TEMPFACT_ANN, true));
493 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
494 Preferences.STRUCT_FROM_PDB, true));
495 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
496 Preferences.USE_RNAVIEW, true));
500 ssm.setAddTempFacAnnot(false);
501 ssm.setProcessSecondaryStructure(false);
502 ssm.setSecStructServices(false);
506 public void checkForNews()
508 final Desktop me = this;
509 // Thread off the news reader, in case there are connection problems.
510 addDialogThread(new Runnable()
515 Cache.log.debug("Starting news thread.");
517 jvnews = new BlogReader(me);
518 showNews.setVisible(true);
519 Cache.log.debug("Completed news thread.");
525 protected void showNews_actionPerformed(ActionEvent e)
527 showNews(showNews.isSelected());
530 void showNews(boolean visible)
533 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
534 showNews.setSelected(visible);
535 if (visible && !jvnews.isVisible())
537 new Thread(new Runnable()
542 long now = System.currentTimeMillis();
543 Desktop.instance.setProgressBar(
544 MessageManager.getString("status.refreshing_news"), now);
545 jvnews.refreshNews();
546 Desktop.instance.setProgressBar(null, now);
555 * recover the last known dimensions for a jalview window
558 * - empty string is desktop, all other windows have unique prefix
559 * @return null or last known dimensions scaled to current geometry (if last
560 * window geom was known)
562 Rectangle getLastKnownDimensions(String windowName)
564 // TODO: lock aspect ratio for scaling desktop Bug #0058199
565 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
566 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
567 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
568 String width = jalview.bin.Cache.getProperty(windowName
570 String height = jalview.bin.Cache.getProperty(windowName
572 if ((x != null) && (y != null) && (width != null) && (height != null))
574 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
575 .parseInt(width), ih = Integer.parseInt(height);
576 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
578 // attempt #1 - try to cope with change in screen geometry - this
579 // version doesn't preserve original jv aspect ratio.
580 // take ratio of current screen size vs original screen size.
581 double sw = ((1f * screenSize.width) / (1f * Integer
582 .parseInt(jalview.bin.Cache
583 .getProperty("SCREENGEOMETRY_WIDTH"))));
584 double sh = ((1f * screenSize.height) / (1f * Integer
585 .parseInt(jalview.bin.Cache
586 .getProperty("SCREENGEOMETRY_HEIGHT"))));
587 // rescale the bounds depending upon the current screen geometry.
588 ix = (int) (ix * sw);
589 iw = (int) (iw * sw);
590 iy = (int) (iy * sh);
591 ih = (int) (ih * sh);
592 while (ix >= screenSize.width)
594 jalview.bin.Cache.log
595 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
596 ix -= screenSize.width;
598 while (iy >= screenSize.height)
600 jalview.bin.Cache.log
601 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
602 iy -= screenSize.height;
604 jalview.bin.Cache.log.debug("Got last known dimensions for "
605 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
608 // return dimensions for new instance
609 return new Rectangle(ix, iy, iw, ih);
614 private void doVamsasClientCheck()
616 if (jalview.bin.Cache.vamsasJarsPresent())
618 setupVamsasDisconnectedGui();
619 VamsasMenu.setVisible(true);
620 final Desktop us = this;
621 VamsasMenu.addMenuListener(new MenuListener()
623 // this listener remembers when the menu was first selected, and
624 // doesn't rebuild the session list until it has been cleared and
626 boolean refresh = true;
629 public void menuCanceled(MenuEvent e)
635 public void menuDeselected(MenuEvent e)
641 public void menuSelected(MenuEvent e)
645 us.buildVamsasStMenu();
650 vamsasStart.setVisible(true);
654 void showPasteMenu(int x, int y)
656 JPopupMenu popup = new JPopupMenu();
657 JMenuItem item = new JMenuItem(
658 MessageManager.getString("label.paste_new_window"));
659 item.addActionListener(new ActionListener()
662 public void actionPerformed(ActionEvent evt)
669 popup.show(this, x, y);
676 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
677 Transferable contents = c.getContents(this);
679 if (contents != null)
681 String file = (String) contents
682 .getTransferData(DataFlavor.stringFlavor);
684 String format = new IdentifyFile().identify(file,
685 FormatAdapter.PASTE);
687 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
690 } catch (Exception ex)
693 .println("Unable to paste alignment from system clipboard:\n"
699 * Adds and opens the given frame to the desktop
710 public static synchronized void addInternalFrame(
711 final JInternalFrame frame, String title, int w, int h)
713 addInternalFrame(frame, title, true, w, h, true);
717 * Add an internal frame to the Jalview desktop
724 * When true, display frame immediately, otherwise, caller must call
725 * setVisible themselves.
731 public static synchronized void addInternalFrame(
732 final JInternalFrame frame, String title, boolean makeVisible,
735 addInternalFrame(frame, title, makeVisible, w, h, true);
739 * Add an internal frame to the Jalview desktop and make it visible
752 public static synchronized void addInternalFrame(
753 final JInternalFrame frame, String title, int w, int h,
756 addInternalFrame(frame, title, true, w, h, resizable);
760 * Add an internal frame to the Jalview desktop
767 * When true, display frame immediately, otherwise, caller must call
768 * setVisible themselves.
776 public static synchronized void addInternalFrame(
777 final JInternalFrame frame, String title, boolean makeVisible,
778 int w, int h, boolean resizable)
781 // TODO: allow callers to determine X and Y position of frame (eg. via
783 // TODO: consider fixing method to update entries in the window submenu with
784 // the current window title
786 frame.setTitle(title);
787 if (frame.getWidth() < 1 || frame.getHeight() < 1)
791 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
792 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
793 // IF JALVIEW IS RUNNING HEADLESS
794 // ///////////////////////////////////////////////
796 || (System.getProperty("java.awt.headless") != null && System
797 .getProperty("java.awt.headless").equals("true")))
804 frame.setVisible(makeVisible);
805 frame.setClosable(true);
806 frame.setResizable(resizable);
807 frame.setMaximizable(resizable);
808 frame.setIconifiable(resizable);
809 if (Platform.isAMac())
811 frame.setIconifiable(false);
812 frame.setFrameIcon(null);
813 // frame.setDesktopIcon(null);
814 frame.setDoubleBuffered(false);
816 if (frame.getX() < 1 && frame.getY() < 1)
818 frame.setLocation(xOffset * openFrameCount, yOffset
819 * ((openFrameCount - 1) % 10) + yOffset);
823 * add an entry for the new frame in the Window menu
824 * (and remove it when the frame is closed)
826 final JMenuItem menuItem = new JMenuItem(title);
827 frame.addInternalFrameListener(new InternalFrameAdapter()
830 public void internalFrameActivated(InternalFrameEvent evt)
832 JInternalFrame itf = desktop.getSelectedFrame();
840 public void internalFrameClosed(InternalFrameEvent evt)
842 PaintRefresher.RemoveComponent(frame);
845 * defensive check to prevent frames being
846 * added half off the window
848 if (openFrameCount > 0)
854 * ensure no reference to alignFrame retained by menu item listener
856 if (menuItem.getActionListeners().length > 0)
858 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
860 windowMenu.remove(menuItem);
861 JInternalFrame itf = desktop.getSelectedFrame();
865 if (itf instanceof AlignFrame)
867 Jalview.setCurrentAlignFrame((AlignFrame) itf);
874 menuItem.addActionListener(new ActionListener()
877 public void actionPerformed(ActionEvent e)
881 frame.setSelected(true);
882 frame.setIcon(false);
883 } catch (java.beans.PropertyVetoException ex)
890 windowMenu.add(menuItem);
896 frame.setSelected(true);
897 frame.requestFocus();
898 } catch (java.beans.PropertyVetoException ve)
900 } catch (java.lang.ClassCastException cex)
903 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
909 public void lostOwnership(Clipboard clipboard, Transferable contents)
913 Desktop.jalviewClipboard = null;
916 internalCopy = false;
920 public void dragEnter(DropTargetDragEvent evt)
925 public void dragExit(DropTargetEvent evt)
930 public void dragOver(DropTargetDragEvent evt)
935 public void dropActionChanged(DropTargetDragEvent evt)
946 public void drop(DropTargetDropEvent evt)
948 boolean success = true;
949 // JAL-1552 - acceptDrop required before getTransferable call for
950 // Java's Transferable for native dnd
951 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
952 Transferable t = evt.getTransferable();
953 java.util.List<String> files = new ArrayList<String>();
954 java.util.List<String> protocols = new ArrayList<String>();
958 Desktop.transferFromDropTarget(files, protocols, evt, t);
959 } catch (Exception e)
969 for (int i = 0; i < files.size(); i++)
971 String file = files.get(i).toString();
972 String protocol = (protocols == null) ? FormatAdapter.FILE
973 : (String) protocols.get(i);
974 String format = null;
976 if (file.endsWith(".jar"))
983 format = new IdentifyFile().identify(file, protocol);
986 new FileLoader().LoadFile(file, protocol, format);
989 } catch (Exception ex)
994 evt.dropComplete(success); // need this to ensure input focus is properly
995 // transfered to any new windows created
1005 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
1007 JalviewFileChooser chooser = new JalviewFileChooser(
1008 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1009 jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
1010 jalview.io.AppletFormatAdapter.READABLE_FNAMES,
1011 jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
1013 chooser.setFileView(new JalviewFileView());
1014 chooser.setDialogTitle(MessageManager
1015 .getString("label.open_local_file"));
1016 chooser.setToolTipText(MessageManager.getString("action.open"));
1018 int value = chooser.showOpenDialog(this);
1020 if (value == JalviewFileChooser.APPROVE_OPTION)
1022 String choice = chooser.getSelectedFile().getPath();
1023 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
1024 .getSelectedFile().getParent());
1026 String format = null;
1027 if (chooser.getSelectedFormat() != null
1028 && chooser.getSelectedFormat().equals("Jalview"))
1034 format = new IdentifyFile().identify(choice, FormatAdapter.FILE);
1037 if (viewport != null)
1039 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
1044 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
1056 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1058 // This construct allows us to have a wider textfield
1060 JLabel label = new JLabel(
1061 MessageManager.getString("label.input_file_url"));
1062 final JComboBox history = new JComboBox();
1064 JPanel panel = new JPanel(new GridLayout(2, 1));
1067 history.setPreferredSize(new Dimension(400, 20));
1068 history.setEditable(true);
1069 history.addItem("http://www.");
1071 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1075 if (historyItems != null)
1077 st = new StringTokenizer(historyItems, "\t");
1079 while (st.hasMoreTokens())
1081 history.addItem(st.nextElement());
1085 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
1086 MessageManager.getString("label.input_alignment_from_url"),
1087 JOptionPane.OK_CANCEL_OPTION);
1089 if (reply != JOptionPane.OK_OPTION)
1094 String url = history.getSelectedItem().toString();
1096 if (url.toLowerCase().endsWith(".jar"))
1098 if (viewport != null)
1100 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1105 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1110 String format = new IdentifyFile().identify(url, FormatAdapter.URL);
1112 if (format.equals("URL NOT FOUND"))
1114 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1115 MessageManager.formatMessage("label.couldnt_locate",
1116 new Object[] { url }), MessageManager
1117 .getString("label.url_not_found"),
1118 JOptionPane.WARNING_MESSAGE);
1123 if (viewport != null)
1125 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1129 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1135 * Opens the CutAndPaste window for the user to paste an alignment in to
1138 * - if not null, the pasted alignment is added to the current
1139 * alignment; if null, to a new alignment window
1142 public void inputTextboxMenuItem_actionPerformed(
1143 AlignmentViewPanel viewPanel)
1145 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1146 cap.setForInput(viewPanel);
1147 Desktop.addInternalFrame(cap,
1148 MessageManager.getString("label.cut_paste_alignmen_file"),
1158 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1160 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1161 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1163 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1164 getBounds().y, getWidth(), getHeight()));
1166 if (jconsole != null)
1168 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1169 jconsole.stopConsole();
1173 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1176 if (dialogExecutor != null)
1178 dialogExecutor.shutdownNow();
1180 closeAll_actionPerformed(null);
1182 if (groovyConsole != null)
1184 // suppress a possible repeat prompt to save script
1185 groovyConsole.setDirty(false);
1186 groovyConsole.exit();
1191 private void storeLastKnownDimensions(String string, Rectangle jc)
1193 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1194 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1195 + " height:" + jc.height);
1197 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1198 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1199 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1200 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1210 public void aboutMenuItem_actionPerformed(ActionEvent e)
1212 // StringBuffer message = getAboutMessage(false);
1213 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1215 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1216 new Thread(new Runnable()
1221 new SplashScreen(true);
1226 public StringBuffer getAboutMessage(boolean shortv)
1228 StringBuffer message = new StringBuffer();
1229 message.append("<html>");
1232 message.append("<h1><strong>Version: "
1233 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1234 message.append("<strong>Last Updated: <em>"
1235 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1236 + "</em></strong>");
1242 message.append("<strong>Version "
1243 + jalview.bin.Cache.getProperty("VERSION")
1244 + "; last updated: "
1245 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1248 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1251 message.append("<br>...Checking latest version...</br>");
1253 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1254 .equals(jalview.bin.Cache.getProperty("VERSION")))
1256 boolean red = false;
1257 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1258 .indexOf("automated build") == -1)
1261 // Displayed when code version and jnlp version do not match and code
1262 // version is not a development build
1263 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1266 message.append("<br>!! Version "
1267 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1269 + " is available for download from "
1270 + jalview.bin.Cache.getDefault("www.jalview.org",
1271 "http://www.jalview.org") + " !!");
1274 message.append("</div>");
1277 message.append("<br>Authors: "
1279 .getDefault("AUTHORFNAMES",
1280 "The Jalview Authors (See AUTHORS file for current list)")
1281 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1282 + "<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"
1283 + "<br><br>If you use Jalview, please cite:"
1284 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1285 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1286 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1298 public void documentationMenuItem_actionPerformed(ActionEvent e)
1302 Help.showHelpWindow();
1303 } catch (Exception ex)
1309 public void closeAll_actionPerformed(ActionEvent e)
1311 // TODO show a progress bar while closing?
1312 JInternalFrame[] frames = desktop.getAllFrames();
1313 for (int i = 0; i < frames.length; i++)
1317 frames[i].setClosed(true);
1318 } catch (java.beans.PropertyVetoException ex)
1322 Jalview.setCurrentAlignFrame(null);
1323 System.out.println("ALL CLOSED");
1324 if (v_client != null)
1326 // TODO clear binding to vamsas document objects on close_all
1330 * reset state of singleton objects as appropriate (clear down session state
1331 * when all windows are closed)
1333 StructureSelectionManager ssm = StructureSelectionManager
1334 .getStructureSelectionManager(this);
1343 public void raiseRelated_actionPerformed(ActionEvent e)
1345 reorderAssociatedWindows(false, false);
1349 public void minimizeAssociated_actionPerformed(ActionEvent e)
1351 reorderAssociatedWindows(true, false);
1354 void closeAssociatedWindows()
1356 reorderAssociatedWindows(false, true);
1362 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1366 protected void garbageCollect_actionPerformed(ActionEvent e)
1368 // We simply collect the garbage
1369 jalview.bin.Cache.log.debug("Collecting garbage...");
1371 jalview.bin.Cache.log.debug("Finished garbage collection.");
1378 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1382 protected void showMemusage_actionPerformed(ActionEvent e)
1384 desktop.showMemoryUsage(showMemusage.isSelected());
1391 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1395 protected void showConsole_actionPerformed(ActionEvent e)
1397 showConsole(showConsole.isSelected());
1400 Console jconsole = null;
1403 * control whether the java console is visible or not
1407 void showConsole(boolean selected)
1409 showConsole.setSelected(selected);
1410 // TODO: decide if we should update properties file
1411 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1413 jconsole.setVisible(selected);
1416 void reorderAssociatedWindows(boolean minimize, boolean close)
1418 JInternalFrame[] frames = desktop.getAllFrames();
1419 if (frames == null || frames.length < 1)
1424 AlignmentViewport source = null, target = null;
1425 if (frames[0] instanceof AlignFrame)
1427 source = ((AlignFrame) frames[0]).getCurrentView();
1429 else if (frames[0] instanceof TreePanel)
1431 source = ((TreePanel) frames[0]).getViewPort();
1433 else if (frames[0] instanceof PCAPanel)
1435 source = ((PCAPanel) frames[0]).av;
1437 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1439 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1444 for (int i = 0; i < frames.length; i++)
1447 if (frames[i] == null)
1451 if (frames[i] instanceof AlignFrame)
1453 target = ((AlignFrame) frames[i]).getCurrentView();
1455 else if (frames[i] instanceof TreePanel)
1457 target = ((TreePanel) frames[i]).getViewPort();
1459 else if (frames[i] instanceof PCAPanel)
1461 target = ((PCAPanel) frames[i]).av;
1463 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1465 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1468 if (source == target)
1474 frames[i].setClosed(true);
1478 frames[i].setIcon(minimize);
1481 frames[i].toFront();
1485 } catch (java.beans.PropertyVetoException ex)
1500 protected void preferences_actionPerformed(ActionEvent e)
1512 public void saveState_actionPerformed(ActionEvent e)
1514 JalviewFileChooser chooser = new JalviewFileChooser(
1515 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
1516 new String[] { "jvp" }, new String[] { "Jalview Project" },
1519 chooser.setFileView(new JalviewFileView());
1520 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1522 int value = chooser.showSaveDialog(this);
1524 if (value == JalviewFileChooser.APPROVE_OPTION)
1526 final Desktop me = this;
1527 final java.io.File choice = chooser.getSelectedFile();
1528 setProjectFile(choice);
1530 new Thread(new Runnable()
1535 // TODO: refactor to Jalview desktop session controller action.
1536 setProgressBar(MessageManager.formatMessage(
1537 "label.saving_jalview_project",
1538 new Object[] { choice.getName() }), choice.hashCode());
1539 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1540 choice.getParent());
1541 // TODO catch and handle errors for savestate
1542 // TODO prevent user from messing with the Desktop whilst we're saving
1545 new Jalview2XML().saveState(choice);
1546 } catch (OutOfMemoryError oom)
1548 new OOMWarning("Whilst saving current state to "
1549 + choice.getName(), oom);
1550 } catch (Exception ex)
1553 "Problems whilst trying to save to " + choice.getName(),
1555 JOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1556 "label.error_whilst_saving_current_state_to",
1557 new Object[] { choice.getName() }), MessageManager
1558 .getString("label.couldnt_save_project"),
1559 JOptionPane.WARNING_MESSAGE);
1561 setProgressBar(null, choice.hashCode());
1567 private void setProjectFile(File choice)
1569 this.projectFile = choice;
1572 public File getProjectFile()
1574 return this.projectFile;
1584 public void loadState_actionPerformed(ActionEvent e)
1586 JalviewFileChooser chooser = new JalviewFileChooser(
1587 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] {
1588 "jvp", "jar" }, new String[] { "Jalview Project",
1589 "Jalview Project (old)" }, "Jalview Project");
1590 chooser.setFileView(new JalviewFileView());
1591 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1593 int value = chooser.showOpenDialog(this);
1595 if (value == JalviewFileChooser.APPROVE_OPTION)
1597 final File selectedFile = chooser.getSelectedFile();
1598 setProjectFile(selectedFile);
1599 final String choice = selectedFile.getAbsolutePath();
1600 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1601 selectedFile.getParent());
1602 new Thread(new Runnable()
1608 MessageManager.formatMessage(
1609 "label.loading_jalview_project",
1610 new Object[] { choice }), choice.hashCode());
1613 new Jalview2XML().loadJalviewAlign(choice);
1614 } catch (OutOfMemoryError oom)
1616 new OOMWarning("Whilst loading project from " + choice, oom);
1617 } catch (Exception ex)
1619 Cache.log.error("Problems whilst loading project from "
1621 JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1623 "label.error_whilst_loading_project_from",
1624 new Object[] { choice }), MessageManager
1625 .getString("label.couldnt_load_project"),
1626 JOptionPane.WARNING_MESSAGE);
1628 setProgressBar(null, choice.hashCode());
1635 public void inputSequence_actionPerformed(ActionEvent e)
1637 new SequenceFetcher(this);
1640 JPanel progressPanel;
1642 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1644 public void startLoading(final String fileName)
1646 if (fileLoadingCount == 0)
1648 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1649 "label.loading_file", new Object[] { fileName })));
1654 private JPanel addProgressPanel(String string)
1656 if (progressPanel == null)
1658 progressPanel = new JPanel(new GridLayout(1, 1));
1659 totalProgressCount = 0;
1660 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1662 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1663 JProgressBar progressBar = new JProgressBar();
1664 progressBar.setIndeterminate(true);
1666 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1668 thisprogress.add(progressBar, BorderLayout.CENTER);
1669 progressPanel.add(thisprogress);
1670 ((GridLayout) progressPanel.getLayout())
1671 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1672 ++totalProgressCount;
1673 instance.validate();
1674 return thisprogress;
1677 int totalProgressCount = 0;
1679 private void removeProgressPanel(JPanel progbar)
1681 if (progressPanel != null)
1683 synchronized (progressPanel)
1685 progressPanel.remove(progbar);
1686 GridLayout gl = (GridLayout) progressPanel.getLayout();
1687 gl.setRows(gl.getRows() - 1);
1688 if (--totalProgressCount < 1)
1690 this.getContentPane().remove(progressPanel);
1691 progressPanel = null;
1698 public void stopLoading()
1701 if (fileLoadingCount < 1)
1703 while (fileLoadingPanels.size() > 0)
1705 removeProgressPanel(fileLoadingPanels.remove(0));
1707 fileLoadingPanels.clear();
1708 fileLoadingCount = 0;
1713 public static int getViewCount(String alignmentId)
1715 AlignmentViewport[] aps = getViewports(alignmentId);
1716 return (aps == null) ? 0 : aps.length;
1721 * @param alignmentId
1722 * - if null, all sets are returned
1723 * @return all AlignmentPanels concerning the alignmentId sequence set
1725 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1727 if (Desktop.desktop == null)
1729 // no frames created and in headless mode
1730 // TODO: verify that frames are recoverable when in headless mode
1733 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1734 AlignFrame[] frames = getAlignFrames();
1739 for (AlignFrame af : frames)
1741 for (AlignmentPanel ap : af.alignPanels)
1743 if (alignmentId == null
1744 || alignmentId.equals(ap.av.getSequenceSetId()))
1750 if (aps.size() == 0)
1754 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1759 * get all the viewports on an alignment.
1761 * @param sequenceSetId
1762 * unique alignment id (may be null - all viewports returned in that
1764 * @return all viewports on the alignment bound to sequenceSetId
1766 public static AlignmentViewport[] getViewports(String sequenceSetId)
1768 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1769 if (desktop != null)
1771 AlignFrame[] frames = Desktop.getAlignFrames();
1773 for (AlignFrame afr : frames)
1775 if (sequenceSetId == null
1776 || afr.getViewport().getSequenceSetId()
1777 .equals(sequenceSetId))
1779 if (afr.alignPanels != null)
1781 for (AlignmentPanel ap : afr.alignPanels)
1783 if (sequenceSetId == null
1784 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1792 viewp.add(afr.getViewport());
1796 if (viewp.size() > 0)
1798 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1805 * Explode the views in the given frame into separate AlignFrame
1809 public static void explodeViews(AlignFrame af)
1811 int size = af.alignPanels.size();
1817 for (int i = 0; i < size; i++)
1819 AlignmentPanel ap = af.alignPanels.get(i);
1820 AlignFrame newaf = new AlignFrame(ap);
1823 * Restore the view's last exploded frame geometry if known. Multiple
1824 * views from one exploded frame share and restore the same (frame)
1825 * position and size.
1827 Rectangle geometry = ap.av.getExplodedGeometry();
1828 if (geometry != null)
1830 newaf.setBounds(geometry);
1833 ap.av.setGatherViewsHere(false);
1835 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1836 AlignFrame.DEFAULT_HEIGHT);
1839 af.alignPanels.clear();
1840 af.closeMenuItem_actionPerformed(true);
1845 * Gather expanded views (separate AlignFrame's) with the same sequence set
1846 * identifier back in to this frame as additional views, and close the
1847 * expanded views. Note the expanded frames may themselves have multiple
1848 * views. We take the lot.
1852 public void gatherViews(AlignFrame source)
1854 source.viewport.setGatherViewsHere(true);
1855 source.viewport.setExplodedGeometry(source.getBounds());
1856 JInternalFrame[] frames = desktop.getAllFrames();
1857 String viewId = source.viewport.getSequenceSetId();
1859 for (int t = 0; t < frames.length; t++)
1861 if (frames[t] instanceof AlignFrame && frames[t] != source)
1863 AlignFrame af = (AlignFrame) frames[t];
1864 boolean gatherThis = false;
1865 for (int a = 0; a < af.alignPanels.size(); a++)
1867 AlignmentPanel ap = af.alignPanels.get(a);
1868 if (viewId.equals(ap.av.getSequenceSetId()))
1871 ap.av.setGatherViewsHere(false);
1872 ap.av.setExplodedGeometry(af.getBounds());
1873 source.addAlignmentPanel(ap, false);
1879 af.alignPanels.clear();
1880 af.closeMenuItem_actionPerformed(true);
1887 jalview.gui.VamsasApplication v_client = null;
1890 public void vamsasImport_actionPerformed(ActionEvent e)
1892 if (v_client == null)
1894 // Load and try to start a session.
1895 JalviewFileChooser chooser = new JalviewFileChooser(
1896 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1898 chooser.setFileView(new JalviewFileView());
1899 chooser.setDialogTitle(MessageManager
1900 .getString("label.open_saved_vamsas_session"));
1901 chooser.setToolTipText(MessageManager
1902 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1904 int value = chooser.showOpenDialog(this);
1906 if (value == JalviewFileChooser.APPROVE_OPTION)
1908 String fle = chooser.getSelectedFile().toString();
1909 if (!vamsasImport(chooser.getSelectedFile()))
1912 .showInternalMessageDialog(
1914 MessageManager.formatMessage(
1915 "label.couldnt_import_as_vamsas_session",
1916 new Object[] { fle }),
1918 .getString("label.vamsas_document_import_failed"),
1919 JOptionPane.ERROR_MESSAGE);
1925 jalview.bin.Cache.log
1926 .error("Implementation error - load session from a running session is not supported.");
1931 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1934 * @return true if import was a success and a session was started.
1936 public boolean vamsasImport(URL url)
1938 // TODO: create progress bar
1939 if (v_client != null)
1942 jalview.bin.Cache.log
1943 .error("Implementation error - load session from a running session is not supported.");
1949 // copy the URL content to a temporary local file
1950 // TODO: be a bit cleverer here with nio (?!)
1951 File file = File.createTempFile("vdocfromurl", ".vdj");
1952 FileOutputStream fos = new FileOutputStream(file);
1953 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1954 byte[] buffer = new byte[2048];
1956 while ((ln = bis.read(buffer)) > -1)
1958 fos.write(buffer, 0, ln);
1962 v_client = new jalview.gui.VamsasApplication(this, file,
1963 url.toExternalForm());
1964 } catch (Exception ex)
1966 jalview.bin.Cache.log.error(
1967 "Failed to create new vamsas session from contents of URL "
1971 setupVamsasConnectedGui();
1972 v_client.initial_update(); // TODO: thread ?
1973 return v_client.inSession();
1977 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1980 * @return true if import was a success and a session was started.
1982 public boolean vamsasImport(File file)
1984 if (v_client != null)
1987 jalview.bin.Cache.log
1988 .error("Implementation error - load session from a running session is not supported.");
1992 setProgressBar(MessageManager.formatMessage(
1993 "status.importing_vamsas_session_from",
1994 new Object[] { file.getName() }), file.hashCode());
1997 v_client = new jalview.gui.VamsasApplication(this, file, null);
1998 } catch (Exception ex)
2000 setProgressBar(MessageManager.formatMessage(
2001 "status.importing_vamsas_session_from",
2002 new Object[] { file.getName() }), file.hashCode());
2003 jalview.bin.Cache.log.error(
2004 "New vamsas session from existing session file failed:", ex);
2007 setupVamsasConnectedGui();
2008 v_client.initial_update(); // TODO: thread ?
2009 setProgressBar(MessageManager.formatMessage(
2010 "status.importing_vamsas_session_from",
2011 new Object[] { file.getName() }), file.hashCode());
2012 return v_client.inSession();
2015 public boolean joinVamsasSession(String mysesid)
2017 if (v_client != null)
2021 .getString("error.try_join_vamsas_session_another"));
2023 if (mysesid == null)
2026 MessageManager.getString("error.invalid_vamsas_session_id"));
2028 v_client = new VamsasApplication(this, mysesid);
2029 setupVamsasConnectedGui();
2030 v_client.initial_update();
2031 return (v_client.inSession());
2035 public void vamsasStart_actionPerformed(ActionEvent e)
2037 if (v_client == null)
2040 // we just start a default session for moment.
2042 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2043 * getProperty("LAST_DIRECTORY"));
2045 * chooser.setFileView(new JalviewFileView());
2046 * chooser.setDialogTitle("Load Vamsas file");
2047 * chooser.setToolTipText("Import");
2049 * int value = chooser.showOpenDialog(this);
2051 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2052 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2054 v_client = new VamsasApplication(this);
2055 setupVamsasConnectedGui();
2056 v_client.initial_update(); // TODO: thread ?
2060 // store current data in session.
2061 v_client.push_update(); // TODO: thread
2065 protected void setupVamsasConnectedGui()
2067 vamsasStart.setText(MessageManager.getString("label.session_update"));
2068 vamsasSave.setVisible(true);
2069 vamsasStop.setVisible(true);
2070 vamsasImport.setVisible(false); // Document import to existing session is
2071 // not possible for vamsas-client-1.0.
2074 protected void setupVamsasDisconnectedGui()
2076 vamsasSave.setVisible(false);
2077 vamsasStop.setVisible(false);
2078 vamsasImport.setVisible(true);
2079 vamsasStart.setText(MessageManager
2080 .getString("label.new_vamsas_session"));
2084 public void vamsasStop_actionPerformed(ActionEvent e)
2086 if (v_client != null)
2088 v_client.end_session();
2090 setupVamsasDisconnectedGui();
2094 protected void buildVamsasStMenu()
2096 if (v_client == null)
2098 String[] sess = null;
2101 sess = VamsasApplication.getSessionList();
2102 } catch (Exception e)
2104 jalview.bin.Cache.log.warn(
2105 "Problem getting current sessions list.", e);
2110 jalview.bin.Cache.log.debug("Got current sessions list: "
2111 + sess.length + " entries.");
2112 VamsasStMenu.removeAll();
2113 for (int i = 0; i < sess.length; i++)
2115 JMenuItem sessit = new JMenuItem();
2116 sessit.setText(sess[i]);
2117 sessit.setToolTipText(MessageManager.formatMessage(
2118 "label.connect_to_session", new Object[] { sess[i] }));
2119 final Desktop dsktp = this;
2120 final String mysesid = sess[i];
2121 sessit.addActionListener(new ActionListener()
2125 public void actionPerformed(ActionEvent e)
2127 if (dsktp.v_client == null)
2129 Thread rthr = new Thread(new Runnable()
2135 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2136 dsktp.setupVamsasConnectedGui();
2137 dsktp.v_client.initial_update();
2145 VamsasStMenu.add(sessit);
2147 // don't show an empty menu.
2148 VamsasStMenu.setVisible(sess.length > 0);
2153 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2154 VamsasStMenu.removeAll();
2155 VamsasStMenu.setVisible(false);
2160 // Not interested in the content. Just hide ourselves.
2161 VamsasStMenu.setVisible(false);
2166 public void vamsasSave_actionPerformed(ActionEvent e)
2168 if (v_client != null)
2170 JalviewFileChooser chooser = new JalviewFileChooser(
2171 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
2172 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2173 new String[] { "Vamsas Document" }, "Vamsas Document");
2175 chooser.setFileView(new JalviewFileView());
2176 chooser.setDialogTitle(MessageManager
2177 .getString("label.save_vamsas_document_archive"));
2179 int value = chooser.showSaveDialog(this);
2181 if (value == JalviewFileChooser.APPROVE_OPTION)
2183 java.io.File choice = chooser.getSelectedFile();
2184 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2185 "label.saving_vamsas_doc",
2186 new Object[] { choice.getName() }));
2187 jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2188 String warnmsg = null;
2189 String warnttl = null;
2192 v_client.vclient.storeDocument(choice);
2195 warnttl = "Serious Problem saving Vamsas Document";
2196 warnmsg = ex.toString();
2197 jalview.bin.Cache.log.error("Error Whilst saving document to "
2200 } catch (Exception ex)
2202 warnttl = "Problem saving Vamsas Document.";
2203 warnmsg = ex.toString();
2204 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2208 removeProgressPanel(progpanel);
2209 if (warnmsg != null)
2211 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2213 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2219 JPanel vamUpdate = null;
2222 * hide vamsas user gui bits when a vamsas document event is being handled.
2225 * true to hide gui, false to reveal gui
2227 public void setVamsasUpdate(boolean b)
2229 jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
2230 + (b ? "in progress" : "finished"));
2232 if (vamUpdate != null)
2234 this.removeProgressPanel(vamUpdate);
2238 vamUpdate = this.addProgressPanel(MessageManager
2239 .getString("label.updating_vamsas_session"));
2241 vamsasStart.setVisible(!b);
2242 vamsasStop.setVisible(!b);
2243 vamsasSave.setVisible(!b);
2246 public JInternalFrame[] getAllFrames()
2248 return desktop.getAllFrames();
2252 * Checks the given url to see if it gives a response indicating that the user
2253 * should be informed of a new questionnaire.
2257 public void checkForQuestionnaire(String url)
2259 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2260 // javax.swing.SwingUtilities.invokeLater(jvq);
2261 new Thread(jvq).start();
2264 public void checkURLLinks()
2266 // Thread off the URL link checker
2267 addDialogThread(new Runnable()
2272 if (Cache.getDefault("CHECKURLLINKS", true))
2274 // check in case URL links use old style tokens ($SEQUENCE_ID$ for
2275 // sequence id _or_ accession id)
2276 JPanel msgPanel = new JPanel();
2277 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2278 msgPanel.add(Box.createVerticalGlue());
2279 JLabel msg = new JLabel(
2281 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2282 JLabel msg2 = new JLabel(
2284 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2288 final JCheckBox jcb = new JCheckBox(
2289 MessageManager.getString("label.do_not_display_again"));
2290 jcb.addActionListener(new ActionListener()
2294 public void actionPerformed(ActionEvent e)
2296 // update Cache settings if checkbox is selected
2297 if (jcb.isSelected())
2299 Cache.setProperty("CHECKURLLINKS", "false");
2303 Cache.setProperty("CHECKURLLINKS", "true");
2309 JOptionPane.showMessageDialog(null, msgPanel, MessageManager
2310 .getString("label.SEQUENCE_ID_no_longer_used"),
2311 JOptionPane.WARNING_MESSAGE);
2318 * Proxy class for JDesktopPane which optionally displays the current memory
2319 * usage and highlights the desktop area with a red bar if free memory runs
2324 public class MyDesktopPane extends JDesktopPane implements Runnable
2327 private static final float ONE_MB = 1048576f;
2329 boolean showMemoryUsage = false;
2333 java.text.NumberFormat df;
2335 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2338 public MyDesktopPane(boolean showMemoryUsage)
2340 showMemoryUsage(showMemoryUsage);
2343 public void showMemoryUsage(boolean showMemory)
2345 this.showMemoryUsage = showMemory;
2348 Thread worker = new Thread(this);
2353 public boolean isShowMemoryUsage()
2355 return showMemoryUsage;
2361 df = java.text.NumberFormat.getNumberInstance();
2362 df.setMaximumFractionDigits(2);
2363 runtime = Runtime.getRuntime();
2365 while (showMemoryUsage)
2369 maxMemory = runtime.maxMemory() / ONE_MB;
2370 allocatedMemory = runtime.totalMemory() / ONE_MB;
2371 freeMemory = runtime.freeMemory() / ONE_MB;
2372 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2374 percentUsage = (totalFreeMemory / maxMemory) * 100;
2376 // if (percentUsage < 20)
2378 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2380 // instance.set.setBorder(border1);
2383 // sleep after showing usage
2385 } catch (Exception ex)
2387 ex.printStackTrace();
2393 public void paintComponent(Graphics g)
2395 if (showMemoryUsage && g != null && df != null)
2397 if (percentUsage < 20)
2399 g.setColor(Color.red);
2401 FontMetrics fm = g.getFontMetrics();
2404 g.drawString(MessageManager.formatMessage(
2405 "label.memory_stats",
2406 new Object[] { df.format(totalFreeMemory),
2407 df.format(maxMemory), df.format(percentUsage) }), 10,
2408 getHeight() - fm.getHeight());
2415 * fixes stacking order after a modal dialog to ensure windows that should be
2416 * on top actually are
2418 public void relayerWindows()
2423 protected JMenuItem groovyShell;
2426 * Accessor method to quickly get all the AlignmentFrames loaded.
2428 * @return an array of AlignFrame, or null if none found
2430 public static AlignFrame[] getAlignFrames()
2432 if (Jalview.isHeadlessMode())
2434 // Desktop.desktop is null in headless mode
2435 return new AlignFrame[] { Jalview.currentAlignFrame };
2438 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2444 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2446 for (int i = frames.length - 1; i > -1; i--)
2448 if (frames[i] instanceof AlignFrame)
2450 avp.add((AlignFrame) frames[i]);
2452 else if (frames[i] instanceof SplitFrame)
2455 * Also check for a split frame containing an AlignFrame
2457 GSplitFrame sf = (GSplitFrame) frames[i];
2458 if (sf.getTopFrame() instanceof AlignFrame)
2460 avp.add((AlignFrame) sf.getTopFrame());
2462 if (sf.getBottomFrame() instanceof AlignFrame)
2464 avp.add((AlignFrame) sf.getBottomFrame());
2468 if (avp.size() == 0)
2472 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2477 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2481 public GStructureViewer[] getJmols()
2483 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2489 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2491 for (int i = frames.length - 1; i > -1; i--)
2493 if (frames[i] instanceof AppJmol)
2495 GStructureViewer af = (GStructureViewer) frames[i];
2499 if (avp.size() == 0)
2503 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2508 * Add Groovy Support to Jalview
2510 public void groovyShell_actionPerformed()
2514 openGroovyConsole();
2515 } catch (Exception ex)
2517 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2518 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2520 MessageManager.getString("label.couldnt_create_groovy_shell"),
2521 MessageManager.getString("label.groovy_support_failed"),
2522 JOptionPane.ERROR_MESSAGE);
2527 * Open the Groovy console
2529 void openGroovyConsole()
2531 if (groovyConsole == null)
2533 groovyConsole = new groovy.ui.Console();
2534 groovyConsole.setVariable("Jalview", this);
2535 groovyConsole.run();
2538 * We allow only one console at a time, so that AlignFrame menu option
2539 * 'Calculate | Run Groovy script' is unambiguous.
2540 * Disable 'Groovy Console', and enable 'Run script', when the console is
2541 * opened, and the reverse when it is closed
2543 Window window = (Window) groovyConsole.getFrame();
2544 window.addWindowListener(new WindowAdapter()
2547 public void windowClosed(WindowEvent e)
2550 * rebind CMD-Q from Groovy Console to Jalview Quit
2553 enableExecuteGroovy(false);
2559 * show Groovy console window (after close and reopen)
2561 ((Window) groovyConsole.getFrame()).setVisible(true);
2564 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2565 * and disable opening a second console
2567 enableExecuteGroovy(true);
2571 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2572 * binding when opened
2574 protected void addQuitHandler()
2576 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2577 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2578 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2579 getRootPane().getActionMap().put("Quit", new AbstractAction()
2582 public void actionPerformed(ActionEvent e)
2590 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2593 * true if Groovy console is open
2595 public void enableExecuteGroovy(boolean enabled)
2598 * disable opening a second Groovy console
2599 * (or re-enable when the console is closed)
2601 groovyShell.setEnabled(!enabled);
2603 AlignFrame[] alignFrames = getAlignFrames();
2604 if (alignFrames != null)
2606 for (AlignFrame af : alignFrames)
2608 af.setGroovyEnabled(enabled);
2614 * Progress bars managed by the IProgressIndicator method.
2616 private Hashtable<Long, JPanel> progressBars;
2618 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2623 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2626 public void setProgressBar(String message, long id)
2628 if (progressBars == null)
2630 progressBars = new Hashtable<Long, JPanel>();
2631 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2634 if (progressBars.get(new Long(id)) != null)
2636 JPanel panel = progressBars.remove(new Long(id));
2637 if (progressBarHandlers.contains(new Long(id)))
2639 progressBarHandlers.remove(new Long(id));
2641 removeProgressPanel(panel);
2645 progressBars.put(new Long(id), addProgressPanel(message));
2652 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2653 * jalview.gui.IProgressIndicatorHandler)
2656 public void registerHandler(final long id,
2657 final IProgressIndicatorHandler handler)
2659 if (progressBarHandlers == null
2660 || !progressBars.containsKey(new Long(id)))
2664 .getString("error.call_setprogressbar_before_registering_handler"));
2666 progressBarHandlers.put(new Long(id), handler);
2667 final JPanel progressPanel = progressBars.get(new Long(id));
2668 if (handler.canCancel())
2670 JButton cancel = new JButton(
2671 MessageManager.getString("action.cancel"));
2672 final IProgressIndicator us = this;
2673 cancel.addActionListener(new ActionListener()
2677 public void actionPerformed(ActionEvent e)
2679 handler.cancelActivity(id);
2680 us.setProgressBar(MessageManager.formatMessage(
2681 "label.cancelled_params",
2682 new Object[] { ((JLabel) progressPanel.getComponent(0))
2686 progressPanel.add(cancel, BorderLayout.EAST);
2692 * @return true if any progress bars are still active
2695 public boolean operationInProgress()
2697 if (progressBars != null && progressBars.size() > 0)
2705 * This will return the first AlignFrame holding the given viewport instance.
2706 * It will break if there are more than one AlignFrames viewing a particular
2710 * @return alignFrame for viewport
2712 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2714 if (desktop != null)
2716 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2717 for (int panel = 0; aps != null && panel < aps.length; panel++)
2719 if (aps[panel] != null && aps[panel].av == viewport)
2721 return aps[panel].alignFrame;
2728 public VamsasApplication getVamsasApplication()
2735 * flag set if jalview GUI is being operated programmatically
2737 private boolean inBatchMode = false;
2740 * check if jalview GUI is being operated programmatically
2742 * @return inBatchMode
2744 public boolean isInBatchMode()
2750 * set flag if jalview GUI is being operated programmatically
2752 * @param inBatchMode
2754 public void setInBatchMode(boolean inBatchMode)
2756 this.inBatchMode = inBatchMode;
2759 public void startServiceDiscovery()
2761 startServiceDiscovery(false);
2764 public void startServiceDiscovery(boolean blocking)
2766 boolean alive = true;
2767 Thread t0 = null, t1 = null, t2 = null;
2768 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2771 // todo: changesupport handlers need to be transferred
2772 if (discoverer == null)
2774 discoverer = new jalview.ws.jws1.Discoverer();
2775 // register PCS handler for desktop.
2776 discoverer.addPropertyChangeListener(changeSupport);
2778 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2779 // until we phase out completely
2780 (t0 = new Thread(discoverer)).start();
2783 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2785 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2787 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2789 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2795 // TODO: do rest service discovery
2804 } catch (Exception e)
2807 alive = (t1 != null && t1.isAlive())
2808 || (t2 != null && t2.isAlive())
2809 || (t3 != null && t3.isAlive())
2810 || (t0 != null && t0.isAlive());
2816 * called to check if the service discovery process completed successfully.
2820 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2822 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2824 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2825 .getErrorMessages();
2828 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2830 if (serviceChangedDialog == null)
2832 // only run if we aren't already displaying one of these.
2833 addDialogThread(serviceChangedDialog = new Runnable()
2840 * JalviewDialog jd =new JalviewDialog() {
2842 * @Override protected void cancelPressed() { // TODO
2843 * Auto-generated method stub
2845 * }@Override protected void okPressed() { // TODO
2846 * Auto-generated method stub
2848 * }@Override protected void raiseClosed() { // TODO
2849 * Auto-generated method stub
2851 * } }; jd.initDialogFrame(new
2852 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2853 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2854 * + " or mis-configured HTTP proxy settings.<br/>" +
2855 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2857 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2858 * ), true, true, "Web Service Configuration Problem", 450,
2861 * jd.waitForInput();
2867 "<html><table width=\"450\"><tr><td>"
2869 + "</td></tr></table>"
2870 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2871 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2872 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2873 + " Tools->Preferences dialog box to change them.</p></html>"),
2874 "Web Service Configuration Problem",
2875 JOptionPane.DEFAULT_OPTION,
2876 JOptionPane.ERROR_MESSAGE);
2877 serviceChangedDialog = null;
2886 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2893 private Runnable serviceChangedDialog = null;
2896 * start a thread to open a URL in the configured browser. Pops up a warning
2897 * dialog to the user if there is an exception when calling out to the browser
2902 public static void showUrl(final String url)
2904 showUrl(url, Desktop.instance);
2908 * Like showUrl but allows progress handler to be specified
2912 * (null) or object implementing IProgressIndicator
2914 public static void showUrl(final String url,
2915 final IProgressIndicator progress)
2917 new Thread(new Runnable()
2924 if (progress != null)
2926 progress.setProgressBar(MessageManager.formatMessage(
2927 "status.opening_params", new Object[] { url }), this
2930 jalview.util.BrowserLauncher.openURL(url);
2931 } catch (Exception ex)
2933 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2935 .getString("label.web_browser_not_found_unix"),
2936 MessageManager.getString("label.web_browser_not_found"),
2937 JOptionPane.WARNING_MESSAGE);
2939 ex.printStackTrace();
2941 if (progress != null)
2943 progress.setProgressBar(null, this.hashCode());
2949 public static WsParamSetManager wsparamManager = null;
2951 public static ParamManager getUserParameterStore()
2953 if (wsparamManager == null)
2955 wsparamManager = new WsParamSetManager();
2957 return wsparamManager;
2961 * static hyperlink handler proxy method for use by Jalview's internal windows
2965 public static void hyperlinkUpdate(HyperlinkEvent e)
2967 if (e.getEventType() == EventType.ACTIVATED)
2972 url = e.getURL().toString();
2973 Desktop.showUrl(url);
2974 } catch (Exception x)
2978 if (Cache.log != null)
2980 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2984 System.err.println("Couldn't handle string " + url
2988 // ignore any exceptions due to dud links.
2995 * single thread that handles display of dialogs to user.
2997 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3000 * flag indicating if dialogExecutor should try to acquire a permit
3002 private volatile boolean dialogPause = true;
3007 private java.util.concurrent.Semaphore block = new Semaphore(0);
3009 private static groovy.ui.Console groovyConsole;
3012 * add another dialog thread to the queue
3016 public void addDialogThread(final Runnable prompter)
3018 dialogExecutor.submit(new Runnable()
3028 } catch (InterruptedException x)
3033 if (instance == null)
3039 SwingUtilities.invokeAndWait(prompter);
3040 } catch (Exception q)
3042 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3048 public void startDialogQueue()
3050 // set the flag so we don't pause waiting for another permit and semaphore
3051 // the current task to begin
3052 dialogPause = false;
3057 protected void snapShotWindow_actionPerformed(ActionEvent e)
3061 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3062 "View of Desktop", getWidth(), getHeight(), of = new File(
3063 "Jalview_snapshot" + System.currentTimeMillis()
3064 + ".eps"), "View of desktop", null, 0, false);
3067 paintAll(im.getGraphics());
3069 } catch (Exception q)
3071 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3075 Cache.log.info("Successfully written snapshot to file "
3076 + of.getAbsolutePath());
3080 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3081 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3082 * and location last time the view was expanded (if any). However it does not
3083 * remember the split pane divider location - this is set to match the
3084 * 'exploding' frame.
3088 public void explodeViews(SplitFrame sf)
3090 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3091 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3092 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3094 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3096 int viewCount = topPanels.size();
3103 * Processing in reverse order works, forwards order leaves the first panels
3104 * not visible. I don't know why!
3106 for (int i = viewCount - 1; i >= 0; i--)
3109 * Make new top and bottom frames. These take over the respective
3110 * AlignmentPanel objects, including their AlignmentViewports, so the
3111 * cdna/protein relationships between the viewports is carried over to the
3114 * explodedGeometry holds the (x, y) position of the previously exploded
3115 * SplitFrame, and the (width, height) of the AlignFrame component
3117 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3118 AlignFrame newTopFrame = new AlignFrame(topPanel);
3119 newTopFrame.setSize(oldTopFrame.getSize());
3120 newTopFrame.setVisible(true);
3121 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3122 .getExplodedGeometry();
3123 if (geometry != null)
3125 newTopFrame.setSize(geometry.getSize());
3128 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3129 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3130 newBottomFrame.setSize(oldBottomFrame.getSize());
3131 newBottomFrame.setVisible(true);
3132 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3133 .getExplodedGeometry();
3134 if (geometry != null)
3136 newBottomFrame.setSize(geometry.getSize());
3139 topPanel.av.setGatherViewsHere(false);
3140 bottomPanel.av.setGatherViewsHere(false);
3141 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3143 if (geometry != null)
3145 splitFrame.setLocation(geometry.getLocation());
3147 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3151 * Clear references to the panels (now relocated in the new SplitFrames)
3152 * before closing the old SplitFrame.
3155 bottomPanels.clear();
3160 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3161 * back into the given SplitFrame as additional views. Note that the gathered
3162 * frames may themselves have multiple views.
3166 public void gatherViews(GSplitFrame source)
3169 * special handling of explodedGeometry for a view within a SplitFrame: - it
3170 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3171 * height) of the AlignFrame component
3173 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3174 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3175 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3176 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3177 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3178 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3180 myTopFrame.viewport.setGatherViewsHere(true);
3181 myBottomFrame.viewport.setGatherViewsHere(true);
3182 String topViewId = myTopFrame.viewport.getSequenceSetId();
3183 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3185 JInternalFrame[] frames = desktop.getAllFrames();
3186 for (JInternalFrame frame : frames)
3188 if (frame instanceof SplitFrame && frame != source)
3190 SplitFrame sf = (SplitFrame) frame;
3191 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3192 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3193 boolean gatherThis = false;
3194 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3196 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3197 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3198 if (topViewId.equals(topPanel.av.getSequenceSetId())
3199 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3202 topPanel.av.setGatherViewsHere(false);
3203 bottomPanel.av.setGatherViewsHere(false);
3204 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3205 topFrame.getSize()));
3206 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3207 .getLocation(), bottomFrame.getSize()));
3208 myTopFrame.addAlignmentPanel(topPanel, false);
3209 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3215 topFrame.getAlignPanels().clear();
3216 bottomFrame.getAlignPanels().clear();
3223 * The dust settles...give focus to the tab we did this from.
3225 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3228 public static groovy.ui.Console getGroovyConsole()
3230 return groovyConsole;
3233 public static void transferFromDropTarget(List<String> files,
3234 List<String> protocols, DropTargetDropEvent evt, Transferable t)
3238 DataFlavor uriListFlavor = new DataFlavor(
3239 "text/uri-list;class=java.lang.String");
3240 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3242 // Works on Windows and MacOSX
3243 Cache.log.debug("Drop handled as javaFileListFlavor");
3244 for (Object file : (List) t
3245 .getTransferData(DataFlavor.javaFileListFlavor))
3247 files.add(((File) file).toString());
3248 protocols.add(FormatAdapter.FILE);
3253 // Unix like behaviour
3254 boolean added = false;
3256 if (t.isDataFlavorSupported(uriListFlavor))
3258 Cache.log.debug("Drop handled as uriListFlavor");
3259 // This is used by Unix drag system
3260 data = (String) t.getTransferData(uriListFlavor);
3264 // fallback to text: workaround - on OSX where there's a JVM bug
3265 Cache.log.debug("standard URIListFlavor failed. Trying text");
3266 // try text fallback
3267 data = (String) t.getTransferData(new DataFlavor(
3268 "text/plain;class=java.lang.String"));
3269 if (Cache.log.isDebugEnabled())
3271 Cache.log.debug("fallback returned " + data);
3274 while (protocols.size() < files.size())
3276 Cache.log.debug("Adding missing FILE protocol for "
3277 + files.get(protocols.size()));
3278 protocols.add(FormatAdapter.FILE);
3280 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3281 data, "\r\n"); st.hasMoreTokens();)
3284 String s = st.nextToken();
3285 if (s.startsWith("#"))
3287 // the line is a comment (as per the RFC 2483)
3290 java.net.URI uri = new java.net.URI(s);
3291 if (uri.getScheme().toLowerCase().startsWith("http"))
3293 protocols.add(FormatAdapter.URL);
3294 files.add(uri.toString());
3298 // otherwise preserve old behaviour: catch all for file objects
3299 java.io.File file = new java.io.File(uri);
3300 protocols.add(FormatAdapter.FILE);
3301 files.add(file.toString());
3304 if (Cache.log.isDebugEnabled())
3306 if (data == null || !added)
3309 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3310 for (DataFlavor fl : t.getTransferDataFlavors())
3312 Cache.log.debug("Supported transfer dataflavor: "
3314 Object df = t.getTransferData(fl);
3317 Cache.log.debug("Retrieves: " + df);
3321 Cache.log.debug("Retrieved nothing");