2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.EMBLEBI_STRING;
24 import static jalview.util.UrlConstants.SEQUENCE_ID;
26 import jalview.api.AlignViewportI;
27 import jalview.api.AlignmentViewPanel;
28 import jalview.bin.Cache;
29 import jalview.bin.Jalview;
30 import jalview.io.DataSourceType;
31 import jalview.io.FileFormat;
32 import jalview.io.FileFormatException;
33 import jalview.io.FileFormatI;
34 import jalview.io.FileLoader;
35 import jalview.io.IdentifyFile;
36 import jalview.io.JalviewFileChooser;
37 import jalview.io.JalviewFileView;
38 import jalview.jbgui.GSplitFrame;
39 import jalview.jbgui.GStructureViewer;
40 import jalview.structure.StructureSelectionManager;
41 import jalview.util.ImageMaker;
42 import jalview.util.MessageManager;
43 import jalview.util.Platform;
44 import jalview.viewmodel.AlignmentViewport;
45 import jalview.ws.params.ParamManager;
47 import java.awt.BorderLayout;
48 import java.awt.Color;
49 import java.awt.Dimension;
50 import java.awt.FontMetrics;
51 import java.awt.Graphics;
52 import java.awt.GridLayout;
53 import java.awt.Point;
54 import java.awt.Rectangle;
55 import java.awt.Toolkit;
56 import java.awt.Window;
57 import java.awt.datatransfer.Clipboard;
58 import java.awt.datatransfer.ClipboardOwner;
59 import java.awt.datatransfer.DataFlavor;
60 import java.awt.datatransfer.Transferable;
61 import java.awt.dnd.DnDConstants;
62 import java.awt.dnd.DropTargetDragEvent;
63 import java.awt.dnd.DropTargetDropEvent;
64 import java.awt.dnd.DropTargetEvent;
65 import java.awt.dnd.DropTargetListener;
66 import java.awt.event.ActionEvent;
67 import java.awt.event.ActionListener;
68 import java.awt.event.FocusEvent;
69 import java.awt.event.FocusListener;
70 import java.awt.event.KeyEvent;
71 import java.awt.event.MouseAdapter;
72 import java.awt.event.MouseEvent;
73 import java.awt.event.WindowAdapter;
74 import java.awt.event.WindowEvent;
75 import java.beans.PropertyChangeEvent;
76 import java.beans.PropertyChangeListener;
77 import java.io.BufferedInputStream;
79 import java.io.FileOutputStream;
81 import java.util.ArrayList;
82 import java.util.Hashtable;
83 import java.util.List;
84 import java.util.ListIterator;
85 import java.util.StringTokenizer;
86 import java.util.Vector;
87 import java.util.concurrent.ExecutorService;
88 import java.util.concurrent.Executors;
89 import java.util.concurrent.Semaphore;
91 import javax.swing.AbstractAction;
92 import javax.swing.Box;
93 import javax.swing.BoxLayout;
94 import javax.swing.DefaultDesktopManager;
95 import javax.swing.DesktopManager;
96 import javax.swing.JButton;
97 import javax.swing.JCheckBox;
98 import javax.swing.JComboBox;
99 import javax.swing.JComponent;
100 import javax.swing.JDesktopPane;
101 import javax.swing.JFrame;
102 import javax.swing.JInternalFrame;
103 import javax.swing.JLabel;
104 import javax.swing.JMenuItem;
105 import javax.swing.JPanel;
106 import javax.swing.JPopupMenu;
107 import javax.swing.JProgressBar;
108 import javax.swing.KeyStroke;
109 import javax.swing.SwingUtilities;
110 import javax.swing.event.HyperlinkEvent;
111 import javax.swing.event.HyperlinkEvent.EventType;
112 import javax.swing.event.InternalFrameAdapter;
113 import javax.swing.event.InternalFrameEvent;
114 import javax.swing.event.MenuEvent;
115 import javax.swing.event.MenuListener;
122 * @version $Revision: 1.155 $
124 public class Desktop extends jalview.jbgui.GDesktop implements
125 DropTargetListener, ClipboardOwner, IProgressIndicator,
126 jalview.api.StructureSelectionManagerProvider
129 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
132 * news reader - null if it was never started.
134 private BlogReader jvnews = null;
136 private File projectFile;
140 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
142 public void addJalviewPropertyChangeListener(
143 PropertyChangeListener listener)
145 changeSupport.addJalviewPropertyChangeListener(listener);
149 * @param propertyName
151 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
152 * java.beans.PropertyChangeListener)
154 public void addJalviewPropertyChangeListener(String propertyName,
155 PropertyChangeListener listener)
157 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
161 * @param propertyName
163 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
164 * java.beans.PropertyChangeListener)
166 public void removeJalviewPropertyChangeListener(String propertyName,
167 PropertyChangeListener listener)
169 changeSupport.removeJalviewPropertyChangeListener(propertyName,
173 /** Singleton Desktop instance */
174 public static Desktop instance;
176 public static MyDesktopPane desktop;
178 static int openFrameCount = 0;
180 static final int xOffset = 30;
182 static final int yOffset = 30;
184 public static jalview.ws.jws1.Discoverer discoverer;
186 public static Object[] jalviewClipboard;
188 public static boolean internalCopy = false;
190 static int fileLoadingCount = 0;
192 class MyDesktopManager implements DesktopManager
195 private DesktopManager delegate;
197 public MyDesktopManager(DesktopManager delegate)
199 this.delegate = delegate;
203 public void activateFrame(JInternalFrame f)
207 delegate.activateFrame(f);
208 } catch (NullPointerException npe)
210 Point p = getMousePosition();
211 instance.showPasteMenu(p.x, p.y);
216 public void beginDraggingFrame(JComponent f)
218 delegate.beginDraggingFrame(f);
222 public void beginResizingFrame(JComponent f, int direction)
224 delegate.beginResizingFrame(f, direction);
228 public void closeFrame(JInternalFrame f)
230 delegate.closeFrame(f);
234 public void deactivateFrame(JInternalFrame f)
236 delegate.deactivateFrame(f);
240 public void deiconifyFrame(JInternalFrame f)
242 delegate.deiconifyFrame(f);
246 public void dragFrame(JComponent f, int newX, int newY)
252 delegate.dragFrame(f, newX, newY);
256 public void endDraggingFrame(JComponent f)
258 delegate.endDraggingFrame(f);
262 public void endResizingFrame(JComponent f)
264 delegate.endResizingFrame(f);
268 public void iconifyFrame(JInternalFrame f)
270 delegate.iconifyFrame(f);
274 public void maximizeFrame(JInternalFrame f)
276 delegate.maximizeFrame(f);
280 public void minimizeFrame(JInternalFrame f)
282 delegate.minimizeFrame(f);
286 public void openFrame(JInternalFrame f)
288 delegate.openFrame(f);
292 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
299 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
303 public void setBoundsForFrame(JComponent f, int newX, int newY,
304 int newWidth, int newHeight)
306 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
309 // All other methods, simply delegate
314 * Creates a new Desktop object.
319 * A note to implementors. It is ESSENTIAL that any activities that might
320 * block are spawned off as threads rather than waited for during this
324 doVamsasClientCheck();
326 groovyShell = new JMenuItem();
327 groovyShell.setText(MessageManager.getString("label.groovy_console"));
328 groovyShell.addActionListener(new ActionListener()
331 public void actionPerformed(ActionEvent e)
333 groovyShell_actionPerformed();
336 toolsMenu.add(groovyShell);
337 groovyShell.setVisible(true);
339 doConfigureStructurePrefs();
340 setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
341 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
342 boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
344 boolean showjconsole = jalview.bin.Cache.getDefault(
345 "SHOW_JAVA_CONSOLE", false);
346 desktop = new MyDesktopPane(selmemusage);
347 if (Platform.isAMac())
349 desktop.setDoubleBuffered(false);
351 showMemusage.setSelected(selmemusage);
352 desktop.setBackground(Color.white);
353 getContentPane().setLayout(new BorderLayout());
354 // alternate config - have scrollbars - see notes in JAL-153
355 // JScrollPane sp = new JScrollPane();
356 // sp.getViewport().setView(desktop);
357 // getContentPane().add(sp, BorderLayout.CENTER);
358 getContentPane().add(desktop, BorderLayout.CENTER);
359 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
361 // This line prevents Windows Look&Feel resizing all new windows to maximum
362 // if previous window was maximised
363 desktop.setDesktopManager(new MyDesktopManager(
364 new DefaultDesktopManager()));
366 Rectangle dims = getLastKnownDimensions("");
373 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
374 setBounds((screenSize.width - 900) / 2,
375 (screenSize.height - 650) / 2, 900, 650);
377 jconsole = new Console(this, showjconsole);
378 // add essential build information
379 jconsole.setHeader("Jalview Version: "
380 + jalview.bin.Cache.getProperty("VERSION") + "\n"
381 + "Jalview Installation: "
382 + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
383 + "\n" + "Build Date: "
384 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
385 + "Java version: " + System.getProperty("java.version") + "\n"
386 + System.getProperty("os.arch") + " "
387 + System.getProperty("os.name") + " "
388 + System.getProperty("os.version"));
390 showConsole(showjconsole);
392 showNews.setVisible(false);
396 this.addWindowListener(new WindowAdapter()
399 public void windowClosing(WindowEvent evt)
406 this.addMouseListener(ma = new MouseAdapter()
409 public void mousePressed(MouseEvent evt)
411 if (evt.isPopupTrigger()) // Mac
413 showPasteMenu(evt.getX(), evt.getY());
418 public void mouseReleased(MouseEvent evt)
420 if (evt.isPopupTrigger()) // Windows
422 showPasteMenu(evt.getX(), evt.getY());
426 desktop.addMouseListener(ma);
428 this.addFocusListener(new FocusListener()
432 public void focusLost(FocusEvent e)
434 // TODO Auto-generated method stub
439 public void focusGained(FocusEvent e)
441 Cache.log.debug("Relaying windows after focus gain");
442 // make sure that we sort windows properly after we gain focus
443 instance.relayerWindows();
446 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
447 // Spawn a thread that shows the splashscreen
448 SwingUtilities.invokeLater(new Runnable()
457 // Thread off a new instance of the file chooser - this reduces the time it
458 // takes to open it later on.
459 new Thread(new Runnable()
464 Cache.log.debug("Filechooser init thread started.");
465 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
466 JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
468 Cache.log.debug("Filechooser init thread finished.");
471 // Add the service change listener
472 changeSupport.addJalviewPropertyChangeListener("services",
473 new PropertyChangeListener()
477 public void propertyChange(PropertyChangeEvent evt)
479 Cache.log.debug("Firing service changed event for "
480 + evt.getNewValue());
481 JalviewServicesChanged(evt);
487 public void doConfigureStructurePrefs()
489 // configure services
490 StructureSelectionManager ssm = StructureSelectionManager
491 .getStructureSelectionManager(this);
492 if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
494 ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
495 Preferences.ADD_TEMPFACT_ANN, true));
496 ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
497 Preferences.STRUCT_FROM_PDB, true));
498 ssm.setSecStructServices(jalview.bin.Cache.getDefault(
499 Preferences.USE_RNAVIEW, true));
503 ssm.setAddTempFacAnnot(false);
504 ssm.setProcessSecondaryStructure(false);
505 ssm.setSecStructServices(false);
509 public void checkForNews()
511 final Desktop me = this;
512 // Thread off the news reader, in case there are connection problems.
513 addDialogThread(new Runnable()
518 Cache.log.debug("Starting news thread.");
520 jvnews = new BlogReader(me);
521 showNews.setVisible(true);
522 Cache.log.debug("Completed news thread.");
528 protected void showNews_actionPerformed(ActionEvent e)
530 showNews(showNews.isSelected());
533 void showNews(boolean visible)
536 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
537 showNews.setSelected(visible);
538 if (visible && !jvnews.isVisible())
540 new Thread(new Runnable()
545 long now = System.currentTimeMillis();
546 Desktop.instance.setProgressBar(
547 MessageManager.getString("status.refreshing_news"), now);
548 jvnews.refreshNews();
549 Desktop.instance.setProgressBar(null, now);
558 * recover the last known dimensions for a jalview window
561 * - empty string is desktop, all other windows have unique prefix
562 * @return null or last known dimensions scaled to current geometry (if last
563 * window geom was known)
565 Rectangle getLastKnownDimensions(String windowName)
567 // TODO: lock aspect ratio for scaling desktop Bug #0058199
568 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
569 String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
570 String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
571 String width = jalview.bin.Cache.getProperty(windowName
573 String height = jalview.bin.Cache.getProperty(windowName
575 if ((x != null) && (y != null) && (width != null) && (height != null))
577 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
578 .parseInt(width), ih = Integer.parseInt(height);
579 if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
581 // attempt #1 - try to cope with change in screen geometry - this
582 // version doesn't preserve original jv aspect ratio.
583 // take ratio of current screen size vs original screen size.
584 double sw = ((1f * screenSize.width) / (1f * Integer
585 .parseInt(jalview.bin.Cache
586 .getProperty("SCREENGEOMETRY_WIDTH"))));
587 double sh = ((1f * screenSize.height) / (1f * Integer
588 .parseInt(jalview.bin.Cache
589 .getProperty("SCREENGEOMETRY_HEIGHT"))));
590 // rescale the bounds depending upon the current screen geometry.
591 ix = (int) (ix * sw);
592 iw = (int) (iw * sw);
593 iy = (int) (iy * sh);
594 ih = (int) (ih * sh);
595 while (ix >= screenSize.width)
597 jalview.bin.Cache.log
598 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
599 ix -= screenSize.width;
601 while (iy >= screenSize.height)
603 jalview.bin.Cache.log
604 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
605 iy -= screenSize.height;
607 jalview.bin.Cache.log.debug("Got last known dimensions for "
608 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
611 // return dimensions for new instance
612 return new Rectangle(ix, iy, iw, ih);
617 private void doVamsasClientCheck()
619 if (jalview.bin.Cache.vamsasJarsPresent())
621 setupVamsasDisconnectedGui();
622 VamsasMenu.setVisible(true);
623 final Desktop us = this;
624 VamsasMenu.addMenuListener(new MenuListener()
626 // this listener remembers when the menu was first selected, and
627 // doesn't rebuild the session list until it has been cleared and
629 boolean refresh = true;
632 public void menuCanceled(MenuEvent e)
638 public void menuDeselected(MenuEvent e)
644 public void menuSelected(MenuEvent e)
648 us.buildVamsasStMenu();
653 vamsasStart.setVisible(true);
657 void showPasteMenu(int x, int y)
659 JPopupMenu popup = new JPopupMenu();
660 JMenuItem item = new JMenuItem(
661 MessageManager.getString("label.paste_new_window"));
662 item.addActionListener(new ActionListener()
665 public void actionPerformed(ActionEvent evt)
672 popup.show(this, x, y);
679 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
680 Transferable contents = c.getContents(this);
682 if (contents != null)
684 String file = (String) contents
685 .getTransferData(DataFlavor.stringFlavor);
687 FileFormatI format = new IdentifyFile().identify(file,
688 DataSourceType.PASTE);
690 new FileLoader().LoadFile(file, DataSourceType.PASTE, format);
693 } catch (Exception ex)
696 .println("Unable to paste alignment from system clipboard:\n"
702 * Adds and opens the given frame to the desktop
713 public static synchronized void addInternalFrame(
714 final JInternalFrame frame, String title, int w, int h)
716 addInternalFrame(frame, title, true, w, h, true);
720 * Add an internal frame to the Jalview desktop
727 * When true, display frame immediately, otherwise, caller must call
728 * setVisible themselves.
734 public static synchronized void addInternalFrame(
735 final JInternalFrame frame, String title, boolean makeVisible,
738 addInternalFrame(frame, title, makeVisible, w, h, true);
742 * Add an internal frame to the Jalview desktop and make it visible
755 public static synchronized void addInternalFrame(
756 final JInternalFrame frame, String title, int w, int h,
759 addInternalFrame(frame, title, true, w, h, resizable);
763 * Add an internal frame to the Jalview desktop
770 * When true, display frame immediately, otherwise, caller must call
771 * setVisible themselves.
779 public static synchronized void addInternalFrame(
780 final JInternalFrame frame, String title, boolean makeVisible,
781 int w, int h, boolean resizable)
784 // TODO: allow callers to determine X and Y position of frame (eg. via
786 // TODO: consider fixing method to update entries in the window submenu with
787 // the current window title
789 frame.setTitle(title);
790 if (frame.getWidth() < 1 || frame.getHeight() < 1)
794 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
795 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
796 // IF JALVIEW IS RUNNING HEADLESS
797 // ///////////////////////////////////////////////
799 || (System.getProperty("java.awt.headless") != null && System
800 .getProperty("java.awt.headless").equals("true")))
807 frame.setVisible(makeVisible);
808 frame.setClosable(true);
809 frame.setResizable(resizable);
810 frame.setMaximizable(resizable);
811 frame.setIconifiable(resizable);
812 if (Platform.isAMac())
814 frame.setIconifiable(false);
815 frame.setFrameIcon(null);
816 // frame.setDesktopIcon(null);
817 frame.setDoubleBuffered(false);
819 if (frame.getX() < 1 && frame.getY() < 1)
821 frame.setLocation(xOffset * openFrameCount, yOffset
822 * ((openFrameCount - 1) % 10) + yOffset);
826 * add an entry for the new frame in the Window menu
827 * (and remove it when the frame is closed)
829 final JMenuItem menuItem = new JMenuItem(title);
830 frame.addInternalFrameListener(new InternalFrameAdapter()
833 public void internalFrameActivated(InternalFrameEvent evt)
835 JInternalFrame itf = desktop.getSelectedFrame();
843 public void internalFrameClosed(InternalFrameEvent evt)
845 PaintRefresher.RemoveComponent(frame);
848 * defensive check to prevent frames being
849 * added half off the window
851 if (openFrameCount > 0)
857 * ensure no reference to alignFrame retained by menu item listener
859 if (menuItem.getActionListeners().length > 0)
861 menuItem.removeActionListener(menuItem.getActionListeners()[0]);
863 windowMenu.remove(menuItem);
864 JInternalFrame itf = desktop.getSelectedFrame();
868 if (itf instanceof AlignFrame)
870 Jalview.setCurrentAlignFrame((AlignFrame) itf);
877 menuItem.addActionListener(new ActionListener()
880 public void actionPerformed(ActionEvent e)
884 frame.setSelected(true);
885 frame.setIcon(false);
886 } catch (java.beans.PropertyVetoException ex)
895 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 List<String> files = new ArrayList<String>();
958 List<DataSourceType> protocols = new ArrayList<DataSourceType>();
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 DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
978 FileFormatI format = null;
980 if (file.endsWith(".jar"))
982 format = FileFormat.Jalview;
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 String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
1012 JalviewFileChooser chooser = JalviewFileChooser.forRead(
1013 Cache.getProperty("LAST_DIRECTORY"), fileFormat);
1015 chooser.setFileView(new JalviewFileView());
1016 chooser.setDialogTitle(MessageManager
1017 .getString("label.open_local_file"));
1018 chooser.setToolTipText(MessageManager.getString("action.open"));
1020 int value = chooser.showOpenDialog(this);
1022 if (value == JalviewFileChooser.APPROVE_OPTION)
1024 String choice = chooser.getSelectedFile().getPath();
1025 Cache.setProperty("LAST_DIRECTORY", chooser
1026 .getSelectedFile().getParent());
1028 FileFormatI format = null;
1029 FileFormatI selectedFormat = chooser.getSelectedFormat();
1030 if (FileFormat.Jalview.equals(selectedFormat))
1032 format = FileFormat.Jalview;
1038 format = new IdentifyFile().identify(choice, DataSourceType.FILE);
1039 } catch (FileFormatException e)
1045 if (viewport != null)
1047 new FileLoader().LoadFile(viewport, choice, DataSourceType.FILE,
1052 new FileLoader().LoadFile(choice, DataSourceType.FILE, format);
1064 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1066 // This construct allows us to have a wider textfield
1068 JLabel label = new JLabel(
1069 MessageManager.getString("label.input_file_url"));
1070 final JComboBox history = new JComboBox();
1072 JPanel panel = new JPanel(new GridLayout(2, 1));
1075 history.setPreferredSize(new Dimension(400, 20));
1076 history.setEditable(true);
1077 history.addItem("http://www.");
1079 String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
1083 if (historyItems != null)
1085 st = new StringTokenizer(historyItems, "\t");
1087 while (st.hasMoreTokens())
1089 history.addItem(st.nextElement());
1093 int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
1094 MessageManager.getString("label.input_alignment_from_url"),
1095 JvOptionPane.OK_CANCEL_OPTION);
1097 if (reply != JvOptionPane.OK_OPTION)
1102 String url = history.getSelectedItem().toString();
1104 if (url.toLowerCase().endsWith(".jar"))
1106 if (viewport != null)
1108 new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
1109 FileFormat.Jalview);
1113 new FileLoader().LoadFile(url, DataSourceType.URL,
1114 FileFormat.Jalview);
1119 FileFormatI format = null;
1122 format = new IdentifyFile().identify(url, DataSourceType.URL);
1123 } catch (FileFormatException e)
1125 // TODO revise error handling, distinguish between
1126 // URL not found and response not valid
1131 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1132 MessageManager.formatMessage("label.couldnt_locate",
1133 new Object[] { url }), MessageManager
1134 .getString("label.url_not_found"),
1135 JvOptionPane.WARNING_MESSAGE);
1140 if (viewport != null)
1143 .LoadFile(viewport, url, DataSourceType.URL, format);
1147 new FileLoader().LoadFile(url, DataSourceType.URL, format);
1153 * Opens the CutAndPaste window for the user to paste an alignment in to
1156 * - if not null, the pasted alignment is added to the current
1157 * alignment; if null, to a new alignment window
1160 public void inputTextboxMenuItem_actionPerformed(
1161 AlignmentViewPanel viewPanel)
1163 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1164 cap.setForInput(viewPanel);
1165 Desktop.addInternalFrame(cap,
1166 MessageManager.getString("label.cut_paste_alignmen_file"),
1176 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1178 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1179 jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1181 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1182 getBounds().y, getWidth(), getHeight()));
1184 if (jconsole != null)
1186 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1187 jconsole.stopConsole();
1191 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1194 if (dialogExecutor != null)
1196 dialogExecutor.shutdownNow();
1198 closeAll_actionPerformed(null);
1200 if (groovyConsole != null)
1202 // suppress a possible repeat prompt to save script
1203 groovyConsole.setDirty(false);
1204 groovyConsole.exit();
1209 private void storeLastKnownDimensions(String string, Rectangle jc)
1211 jalview.bin.Cache.log.debug("Storing last known dimensions for "
1212 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1213 + " height:" + jc.height);
1215 jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + "");
1216 jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1217 jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1218 jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1228 public void aboutMenuItem_actionPerformed(ActionEvent e)
1230 // StringBuffer message = getAboutMessage(false);
1231 // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1233 // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE);
1234 new Thread(new Runnable()
1239 new SplashScreen(true);
1244 public StringBuffer getAboutMessage(boolean shortv)
1246 StringBuffer message = new StringBuffer();
1247 message.append("<html>");
1250 message.append("<h1><strong>Version: "
1251 + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
1252 message.append("<strong>Last Updated: <em>"
1253 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
1254 + "</em></strong>");
1260 message.append("<strong>Version "
1261 + jalview.bin.Cache.getProperty("VERSION")
1262 + "; last updated: "
1263 + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
1266 if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
1269 message.append("<br>...Checking latest version...</br>");
1271 else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
1272 .equals(jalview.bin.Cache.getProperty("VERSION")))
1274 boolean red = false;
1275 if (jalview.bin.Cache.getProperty("VERSION").toLowerCase()
1276 .indexOf("automated build") == -1)
1279 // Displayed when code version and jnlp version do not match and code
1280 // version is not a development build
1281 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1284 message.append("<br>!! Version "
1285 + jalview.bin.Cache.getDefault("LATEST_VERSION",
1287 + " is available for download from "
1288 + jalview.bin.Cache.getDefault("www.jalview.org",
1289 "http://www.jalview.org") + " !!");
1292 message.append("</div>");
1295 message.append("<br>Authors: "
1297 .getDefault("AUTHORFNAMES",
1298 "The Jalview Authors (See AUTHORS file for current list)")
1299 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1300 + "<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"
1301 + "<br><br>If you use Jalview, please cite:"
1302 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1303 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1304 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1316 public void documentationMenuItem_actionPerformed(ActionEvent e)
1320 Help.showHelpWindow();
1321 } catch (Exception ex)
1327 public void closeAll_actionPerformed(ActionEvent e)
1329 // TODO show a progress bar while closing?
1330 JInternalFrame[] frames = desktop.getAllFrames();
1331 for (int i = 0; i < frames.length; i++)
1335 frames[i].setClosed(true);
1336 } catch (java.beans.PropertyVetoException ex)
1340 Jalview.setCurrentAlignFrame(null);
1341 System.out.println("ALL CLOSED");
1342 if (v_client != null)
1344 // TODO clear binding to vamsas document objects on close_all
1348 * reset state of singleton objects as appropriate (clear down session state
1349 * when all windows are closed)
1351 StructureSelectionManager ssm = StructureSelectionManager
1352 .getStructureSelectionManager(this);
1361 public void raiseRelated_actionPerformed(ActionEvent e)
1363 reorderAssociatedWindows(false, false);
1367 public void minimizeAssociated_actionPerformed(ActionEvent e)
1369 reorderAssociatedWindows(true, false);
1372 void closeAssociatedWindows()
1374 reorderAssociatedWindows(false, true);
1380 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1384 protected void garbageCollect_actionPerformed(ActionEvent e)
1386 // We simply collect the garbage
1387 jalview.bin.Cache.log.debug("Collecting garbage...");
1389 jalview.bin.Cache.log.debug("Finished garbage collection.");
1396 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1400 protected void showMemusage_actionPerformed(ActionEvent e)
1402 desktop.showMemoryUsage(showMemusage.isSelected());
1409 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1413 protected void showConsole_actionPerformed(ActionEvent e)
1415 showConsole(showConsole.isSelected());
1418 Console jconsole = null;
1421 * control whether the java console is visible or not
1425 void showConsole(boolean selected)
1427 showConsole.setSelected(selected);
1428 // TODO: decide if we should update properties file
1429 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1431 jconsole.setVisible(selected);
1434 void reorderAssociatedWindows(boolean minimize, boolean close)
1436 JInternalFrame[] frames = desktop.getAllFrames();
1437 if (frames == null || frames.length < 1)
1442 AlignmentViewport source = null, target = null;
1443 if (frames[0] instanceof AlignFrame)
1445 source = ((AlignFrame) frames[0]).getCurrentView();
1447 else if (frames[0] instanceof TreePanel)
1449 source = ((TreePanel) frames[0]).getViewPort();
1451 else if (frames[0] instanceof PCAPanel)
1453 source = ((PCAPanel) frames[0]).av;
1455 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1457 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1462 for (int i = 0; i < frames.length; i++)
1465 if (frames[i] == null)
1469 if (frames[i] instanceof AlignFrame)
1471 target = ((AlignFrame) frames[i]).getCurrentView();
1473 else if (frames[i] instanceof TreePanel)
1475 target = ((TreePanel) frames[i]).getViewPort();
1477 else if (frames[i] instanceof PCAPanel)
1479 target = ((PCAPanel) frames[i]).av;
1481 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1483 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1486 if (source == target)
1492 frames[i].setClosed(true);
1496 frames[i].setIcon(minimize);
1499 frames[i].toFront();
1503 } catch (java.beans.PropertyVetoException ex)
1518 protected void preferences_actionPerformed(ActionEvent e)
1530 public void saveState_actionPerformed(ActionEvent e)
1532 JalviewFileChooser chooser = new JalviewFileChooser(
1533 Cache.getProperty("LAST_DIRECTORY"), "jvp", "Jalview Project");
1535 chooser.setFileView(new JalviewFileView());
1536 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1538 int value = chooser.showSaveDialog(this);
1540 if (value == JalviewFileChooser.APPROVE_OPTION)
1542 final Desktop me = this;
1543 final java.io.File choice = chooser.getSelectedFile();
1544 setProjectFile(choice);
1546 new Thread(new Runnable()
1551 // TODO: refactor to Jalview desktop session controller action.
1552 setProgressBar(MessageManager.formatMessage(
1553 "label.saving_jalview_project",
1554 new Object[] { choice.getName() }), choice.hashCode());
1555 jalview.bin.Cache.setProperty("LAST_DIRECTORY",
1556 choice.getParent());
1557 // TODO catch and handle errors for savestate
1558 // TODO prevent user from messing with the Desktop whilst we're saving
1561 new Jalview2XML().saveState(choice);
1562 } catch (OutOfMemoryError oom)
1564 new OOMWarning("Whilst saving current state to "
1565 + choice.getName(), oom);
1566 } catch (Exception ex)
1569 "Problems whilst trying to save to " + choice.getName(),
1571 JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1572 "label.error_whilst_saving_current_state_to",
1573 new Object[] { choice.getName() }), MessageManager
1574 .getString("label.couldnt_save_project"),
1575 JvOptionPane.WARNING_MESSAGE);
1577 setProgressBar(null, choice.hashCode());
1583 private void setProjectFile(File choice)
1585 this.projectFile = choice;
1588 public File getProjectFile()
1590 return this.projectFile;
1600 public void loadState_actionPerformed(ActionEvent e)
1602 JalviewFileChooser chooser = new JalviewFileChooser(
1603 Cache.getProperty("LAST_DIRECTORY"), new String[] {
1604 "jvp", "jar" }, new String[] { "Jalview Project",
1605 "Jalview Project (old)" }, "Jalview Project");
1606 chooser.setFileView(new JalviewFileView());
1607 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1609 int value = chooser.showOpenDialog(this);
1611 if (value == JalviewFileChooser.APPROVE_OPTION)
1613 final File selectedFile = chooser.getSelectedFile();
1614 setProjectFile(selectedFile);
1615 final String choice = selectedFile.getAbsolutePath();
1616 Cache.setProperty("LAST_DIRECTORY",
1617 selectedFile.getParent());
1618 new Thread(new Runnable()
1624 MessageManager.formatMessage(
1625 "label.loading_jalview_project",
1626 new Object[] { choice }), choice.hashCode());
1629 new Jalview2XML().loadJalviewAlign(choice);
1630 } catch (OutOfMemoryError oom)
1632 new OOMWarning("Whilst loading project from " + choice, oom);
1633 } catch (Exception ex)
1635 Cache.log.error("Problems whilst loading project from "
1637 JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1639 "label.error_whilst_loading_project_from",
1640 new Object[] { choice }), MessageManager
1641 .getString("label.couldnt_load_project"),
1642 JvOptionPane.WARNING_MESSAGE);
1644 setProgressBar(null, choice.hashCode());
1651 public void inputSequence_actionPerformed(ActionEvent e)
1653 new SequenceFetcher(this);
1656 JPanel progressPanel;
1658 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1660 public void startLoading(final String fileName)
1662 if (fileLoadingCount == 0)
1664 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1665 "label.loading_file", new Object[] { fileName })));
1670 private JPanel addProgressPanel(String string)
1672 if (progressPanel == null)
1674 progressPanel = new JPanel(new GridLayout(1, 1));
1675 totalProgressCount = 0;
1676 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1678 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1679 JProgressBar progressBar = new JProgressBar();
1680 progressBar.setIndeterminate(true);
1682 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1684 thisprogress.add(progressBar, BorderLayout.CENTER);
1685 progressPanel.add(thisprogress);
1686 ((GridLayout) progressPanel.getLayout())
1687 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1688 ++totalProgressCount;
1689 instance.validate();
1690 return thisprogress;
1693 int totalProgressCount = 0;
1695 private void removeProgressPanel(JPanel progbar)
1697 if (progressPanel != null)
1699 synchronized (progressPanel)
1701 progressPanel.remove(progbar);
1702 GridLayout gl = (GridLayout) progressPanel.getLayout();
1703 gl.setRows(gl.getRows() - 1);
1704 if (--totalProgressCount < 1)
1706 this.getContentPane().remove(progressPanel);
1707 progressPanel = null;
1714 public void stopLoading()
1717 if (fileLoadingCount < 1)
1719 while (fileLoadingPanels.size() > 0)
1721 removeProgressPanel(fileLoadingPanels.remove(0));
1723 fileLoadingPanels.clear();
1724 fileLoadingCount = 0;
1729 public static int getViewCount(String alignmentId)
1731 AlignmentViewport[] aps = getViewports(alignmentId);
1732 return (aps == null) ? 0 : aps.length;
1737 * @param alignmentId
1738 * - if null, all sets are returned
1739 * @return all AlignmentPanels concerning the alignmentId sequence set
1741 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1743 if (Desktop.desktop == null)
1745 // no frames created and in headless mode
1746 // TODO: verify that frames are recoverable when in headless mode
1749 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1750 AlignFrame[] frames = getAlignFrames();
1755 for (AlignFrame af : frames)
1757 for (AlignmentPanel ap : af.alignPanels)
1759 if (alignmentId == null
1760 || alignmentId.equals(ap.av.getSequenceSetId()))
1766 if (aps.size() == 0)
1770 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1775 * get all the viewports on an alignment.
1777 * @param sequenceSetId
1778 * unique alignment id (may be null - all viewports returned in that
1780 * @return all viewports on the alignment bound to sequenceSetId
1782 public static AlignmentViewport[] getViewports(String sequenceSetId)
1784 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1785 if (desktop != null)
1787 AlignFrame[] frames = Desktop.getAlignFrames();
1789 for (AlignFrame afr : frames)
1791 if (sequenceSetId == null
1792 || afr.getViewport().getSequenceSetId()
1793 .equals(sequenceSetId))
1795 if (afr.alignPanels != null)
1797 for (AlignmentPanel ap : afr.alignPanels)
1799 if (sequenceSetId == null
1800 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1808 viewp.add(afr.getViewport());
1812 if (viewp.size() > 0)
1814 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1821 * Explode the views in the given frame into separate AlignFrame
1825 public static void explodeViews(AlignFrame af)
1827 int size = af.alignPanels.size();
1833 for (int i = 0; i < size; i++)
1835 AlignmentPanel ap = af.alignPanels.get(i);
1836 AlignFrame newaf = new AlignFrame(ap);
1839 * Restore the view's last exploded frame geometry if known. Multiple
1840 * views from one exploded frame share and restore the same (frame)
1841 * position and size.
1843 Rectangle geometry = ap.av.getExplodedGeometry();
1844 if (geometry != null)
1846 newaf.setBounds(geometry);
1849 ap.av.setGatherViewsHere(false);
1851 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1852 AlignFrame.DEFAULT_HEIGHT);
1855 af.alignPanels.clear();
1856 af.closeMenuItem_actionPerformed(true);
1861 * Gather expanded views (separate AlignFrame's) with the same sequence set
1862 * identifier back in to this frame as additional views, and close the
1863 * expanded views. Note the expanded frames may themselves have multiple
1864 * views. We take the lot.
1868 public void gatherViews(AlignFrame source)
1870 source.viewport.setGatherViewsHere(true);
1871 source.viewport.setExplodedGeometry(source.getBounds());
1872 JInternalFrame[] frames = desktop.getAllFrames();
1873 String viewId = source.viewport.getSequenceSetId();
1875 for (int t = 0; t < frames.length; t++)
1877 if (frames[t] instanceof AlignFrame && frames[t] != source)
1879 AlignFrame af = (AlignFrame) frames[t];
1880 boolean gatherThis = false;
1881 for (int a = 0; a < af.alignPanels.size(); a++)
1883 AlignmentPanel ap = af.alignPanels.get(a);
1884 if (viewId.equals(ap.av.getSequenceSetId()))
1887 ap.av.setGatherViewsHere(false);
1888 ap.av.setExplodedGeometry(af.getBounds());
1889 source.addAlignmentPanel(ap, false);
1895 af.alignPanels.clear();
1896 af.closeMenuItem_actionPerformed(true);
1903 jalview.gui.VamsasApplication v_client = null;
1906 public void vamsasImport_actionPerformed(ActionEvent e)
1908 if (v_client == null)
1910 // Load and try to start a session.
1911 JalviewFileChooser chooser = new JalviewFileChooser(
1912 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1914 chooser.setFileView(new JalviewFileView());
1915 chooser.setDialogTitle(MessageManager
1916 .getString("label.open_saved_vamsas_session"));
1917 chooser.setToolTipText(MessageManager
1918 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1920 int value = chooser.showOpenDialog(this);
1922 if (value == JalviewFileChooser.APPROVE_OPTION)
1924 String fle = chooser.getSelectedFile().toString();
1925 if (!vamsasImport(chooser.getSelectedFile()))
1928 .showInternalMessageDialog(
1930 MessageManager.formatMessage(
1931 "label.couldnt_import_as_vamsas_session",
1932 new Object[] { fle }),
1934 .getString("label.vamsas_document_import_failed"),
1935 JvOptionPane.ERROR_MESSAGE);
1941 jalview.bin.Cache.log
1942 .error("Implementation error - load session from a running session is not supported.");
1947 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1950 * @return true if import was a success and a session was started.
1952 public boolean vamsasImport(URL url)
1954 // TODO: create progress bar
1955 if (v_client != null)
1958 jalview.bin.Cache.log
1959 .error("Implementation error - load session from a running session is not supported.");
1965 // copy the URL content to a temporary local file
1966 // TODO: be a bit cleverer here with nio (?!)
1967 File file = File.createTempFile("vdocfromurl", ".vdj");
1968 FileOutputStream fos = new FileOutputStream(file);
1969 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1970 byte[] buffer = new byte[2048];
1972 while ((ln = bis.read(buffer)) > -1)
1974 fos.write(buffer, 0, ln);
1978 v_client = new jalview.gui.VamsasApplication(this, file,
1979 url.toExternalForm());
1980 } catch (Exception ex)
1982 jalview.bin.Cache.log.error(
1983 "Failed to create new vamsas session from contents of URL "
1987 setupVamsasConnectedGui();
1988 v_client.initial_update(); // TODO: thread ?
1989 return v_client.inSession();
1993 * import file into a new vamsas session (uses jalview.gui.VamsasApplication)
1996 * @return true if import was a success and a session was started.
1998 public boolean vamsasImport(File file)
2000 if (v_client != null)
2003 jalview.bin.Cache.log
2004 .error("Implementation error - load session from a running session is not supported.");
2008 setProgressBar(MessageManager.formatMessage(
2009 "status.importing_vamsas_session_from",
2010 new Object[] { file.getName() }), file.hashCode());
2013 v_client = new jalview.gui.VamsasApplication(this, file, null);
2014 } catch (Exception ex)
2016 setProgressBar(MessageManager.formatMessage(
2017 "status.importing_vamsas_session_from",
2018 new Object[] { file.getName() }), file.hashCode());
2019 jalview.bin.Cache.log.error(
2020 "New vamsas session from existing session file failed:", ex);
2023 setupVamsasConnectedGui();
2024 v_client.initial_update(); // TODO: thread ?
2025 setProgressBar(MessageManager.formatMessage(
2026 "status.importing_vamsas_session_from",
2027 new Object[] { file.getName() }), file.hashCode());
2028 return v_client.inSession();
2031 public boolean joinVamsasSession(String mysesid)
2033 if (v_client != null)
2037 .getString("error.try_join_vamsas_session_another"));
2039 if (mysesid == null)
2042 MessageManager.getString("error.invalid_vamsas_session_id"));
2044 v_client = new VamsasApplication(this, mysesid);
2045 setupVamsasConnectedGui();
2046 v_client.initial_update();
2047 return (v_client.inSession());
2051 public void vamsasStart_actionPerformed(ActionEvent e)
2053 if (v_client == null)
2056 // we just start a default session for moment.
2058 * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2059 * getProperty("LAST_DIRECTORY"));
2061 * chooser.setFileView(new JalviewFileView());
2062 * chooser.setDialogTitle("Load Vamsas file");
2063 * chooser.setToolTipText("Import");
2065 * int value = chooser.showOpenDialog(this);
2067 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2068 * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
2070 v_client = new VamsasApplication(this);
2071 setupVamsasConnectedGui();
2072 v_client.initial_update(); // TODO: thread ?
2076 // store current data in session.
2077 v_client.push_update(); // TODO: thread
2081 protected void setupVamsasConnectedGui()
2083 vamsasStart.setText(MessageManager.getString("label.session_update"));
2084 vamsasSave.setVisible(true);
2085 vamsasStop.setVisible(true);
2086 vamsasImport.setVisible(false); // Document import to existing session is
2087 // not possible for vamsas-client-1.0.
2090 protected void setupVamsasDisconnectedGui()
2092 vamsasSave.setVisible(false);
2093 vamsasStop.setVisible(false);
2094 vamsasImport.setVisible(true);
2095 vamsasStart.setText(MessageManager
2096 .getString("label.new_vamsas_session"));
2100 public void vamsasStop_actionPerformed(ActionEvent e)
2102 if (v_client != null)
2104 v_client.end_session();
2106 setupVamsasDisconnectedGui();
2110 protected void buildVamsasStMenu()
2112 if (v_client == null)
2114 String[] sess = null;
2117 sess = VamsasApplication.getSessionList();
2118 } catch (Exception e)
2120 jalview.bin.Cache.log.warn(
2121 "Problem getting current sessions list.", e);
2126 jalview.bin.Cache.log.debug("Got current sessions list: "
2127 + sess.length + " entries.");
2128 VamsasStMenu.removeAll();
2129 for (int i = 0; i < sess.length; i++)
2131 JMenuItem sessit = new JMenuItem();
2132 sessit.setText(sess[i]);
2133 sessit.setToolTipText(MessageManager.formatMessage(
2134 "label.connect_to_session", new Object[] { sess[i] }));
2135 final Desktop dsktp = this;
2136 final String mysesid = sess[i];
2137 sessit.addActionListener(new ActionListener()
2141 public void actionPerformed(ActionEvent e)
2143 if (dsktp.v_client == null)
2145 Thread rthr = new Thread(new Runnable()
2151 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2152 dsktp.setupVamsasConnectedGui();
2153 dsktp.v_client.initial_update();
2161 VamsasStMenu.add(sessit);
2163 // don't show an empty menu.
2164 VamsasStMenu.setVisible(sess.length > 0);
2169 jalview.bin.Cache.log.debug("No current vamsas sessions.");
2170 VamsasStMenu.removeAll();
2171 VamsasStMenu.setVisible(false);
2176 // Not interested in the content. Just hide ourselves.
2177 VamsasStMenu.setVisible(false);
2182 public void vamsasSave_actionPerformed(ActionEvent e)
2184 if (v_client != null)
2186 JalviewFileChooser chooser = new JalviewFileChooser(
2187 Cache.getProperty("LAST_DIRECTORY"), "vdj",// TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2190 chooser.setFileView(new JalviewFileView());
2191 chooser.setDialogTitle(MessageManager
2192 .getString("label.save_vamsas_document_archive"));
2194 int value = chooser.showSaveDialog(this);
2196 if (value == JalviewFileChooser.APPROVE_OPTION)
2198 java.io.File choice = chooser.getSelectedFile();
2199 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2200 "label.saving_vamsas_doc",
2201 new Object[] { choice.getName() }));
2202 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2203 String warnmsg = null;
2204 String warnttl = null;
2207 v_client.vclient.storeDocument(choice);
2210 warnttl = "Serious Problem saving Vamsas Document";
2211 warnmsg = ex.toString();
2212 jalview.bin.Cache.log.error("Error Whilst saving document to "
2215 } catch (Exception ex)
2217 warnttl = "Problem saving Vamsas Document.";
2218 warnmsg = ex.toString();
2219 jalview.bin.Cache.log.warn("Exception Whilst saving document to "
2223 removeProgressPanel(progpanel);
2224 if (warnmsg != null)
2226 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2228 warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
2234 JPanel vamUpdate = null;
2237 * hide vamsas user gui bits when a vamsas document event is being handled.
2240 * true to hide gui, false to reveal gui
2242 public void setVamsasUpdate(boolean b)
2244 Cache.log.debug("Setting gui for Vamsas update "
2245 + (b ? "in progress" : "finished"));
2247 if (vamUpdate != null)
2249 this.removeProgressPanel(vamUpdate);
2253 vamUpdate = this.addProgressPanel(MessageManager
2254 .getString("label.updating_vamsas_session"));
2256 vamsasStart.setVisible(!b);
2257 vamsasStop.setVisible(!b);
2258 vamsasSave.setVisible(!b);
2261 public JInternalFrame[] getAllFrames()
2263 return desktop.getAllFrames();
2267 * Checks the given url to see if it gives a response indicating that the user
2268 * should be informed of a new questionnaire.
2272 public void checkForQuestionnaire(String url)
2274 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2275 // javax.swing.SwingUtilities.invokeLater(jvq);
2276 new Thread(jvq).start();
2279 public void checkURLLinks()
2281 // Thread off the URL link checker
2282 addDialogThread(new Runnable()
2287 if (Cache.getDefault("CHECKURLLINKS", true))
2289 // check what the actual links are - if it's just the default don't
2290 // bother with the warning
2291 Vector<String> links = Preferences.sequenceURLLinks;
2293 // only need to check links if there is one with a
2294 // SEQUENCE_ID which is not the default EMBL_EBI link
2295 ListIterator<String> li = links.listIterator();
2296 boolean check = false;
2297 List<JLabel> urls = new ArrayList<JLabel>();
2298 while (li.hasNext())
2300 String link = li.next();
2301 if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
2304 int barPos = link.indexOf("|");
2305 String urlMsg = barPos == -1 ? link : link.substring(0,
2306 barPos) + ": " + link.substring(barPos + 1);
2307 urls.add(new JLabel(urlMsg));
2315 // ask user to check in case URL links use old style tokens
2316 // ($SEQUENCE_ID$ for sequence id _or_ accession id)
2317 JPanel msgPanel = new JPanel();
2318 msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
2319 msgPanel.add(Box.createVerticalGlue());
2320 JLabel msg = new JLabel(
2322 .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
2323 JLabel msg2 = new JLabel(
2325 .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
2327 for (JLabel url : urls)
2333 final JCheckBox jcb = new JCheckBox(
2334 MessageManager.getString("label.do_not_display_again"));
2335 jcb.addActionListener(new ActionListener()
2338 public void actionPerformed(ActionEvent e)
2340 // update Cache settings for "don't show this again"
2341 boolean showWarningAgain = !jcb.isSelected();
2342 Cache.setProperty("CHECKURLLINKS",
2343 Boolean.valueOf(showWarningAgain).toString());
2348 JvOptionPane.showMessageDialog(Desktop.desktop, msgPanel,
2350 .getString("label.SEQUENCE_ID_no_longer_used"),
2351 JvOptionPane.WARNING_MESSAGE);
2358 * Proxy class for JDesktopPane which optionally displays the current memory
2359 * usage and highlights the desktop area with a red bar if free memory runs
2364 public class MyDesktopPane extends JDesktopPane implements Runnable
2367 private static final float ONE_MB = 1048576f;
2369 boolean showMemoryUsage = false;
2373 java.text.NumberFormat df;
2375 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2378 public MyDesktopPane(boolean showMemoryUsage)
2380 showMemoryUsage(showMemoryUsage);
2383 public void showMemoryUsage(boolean showMemory)
2385 this.showMemoryUsage = showMemory;
2388 Thread worker = new Thread(this);
2393 public boolean isShowMemoryUsage()
2395 return showMemoryUsage;
2401 df = java.text.NumberFormat.getNumberInstance();
2402 df.setMaximumFractionDigits(2);
2403 runtime = Runtime.getRuntime();
2405 while (showMemoryUsage)
2409 maxMemory = runtime.maxMemory() / ONE_MB;
2410 allocatedMemory = runtime.totalMemory() / ONE_MB;
2411 freeMemory = runtime.freeMemory() / ONE_MB;
2412 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2414 percentUsage = (totalFreeMemory / maxMemory) * 100;
2416 // if (percentUsage < 20)
2418 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2420 // instance.set.setBorder(border1);
2423 // sleep after showing usage
2425 } catch (Exception ex)
2427 ex.printStackTrace();
2433 public void paintComponent(Graphics g)
2435 if (showMemoryUsage && g != null && df != null)
2437 if (percentUsage < 20)
2439 g.setColor(Color.red);
2441 FontMetrics fm = g.getFontMetrics();
2444 g.drawString(MessageManager.formatMessage(
2445 "label.memory_stats",
2446 new Object[] { df.format(totalFreeMemory),
2447 df.format(maxMemory), df.format(percentUsage) }), 10,
2448 getHeight() - fm.getHeight());
2455 * fixes stacking order after a modal dialog to ensure windows that should be
2456 * on top actually are
2458 public void relayerWindows()
2463 protected JMenuItem groovyShell;
2466 * Accessor method to quickly get all the AlignmentFrames loaded.
2468 * @return an array of AlignFrame, or null if none found
2470 public static AlignFrame[] getAlignFrames()
2472 if (Jalview.isHeadlessMode())
2474 // Desktop.desktop is null in headless mode
2475 return new AlignFrame[] { Jalview.currentAlignFrame };
2478 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2484 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2486 for (int i = frames.length - 1; i > -1; i--)
2488 if (frames[i] instanceof AlignFrame)
2490 avp.add((AlignFrame) frames[i]);
2492 else if (frames[i] instanceof SplitFrame)
2495 * Also check for a split frame containing an AlignFrame
2497 GSplitFrame sf = (GSplitFrame) frames[i];
2498 if (sf.getTopFrame() instanceof AlignFrame)
2500 avp.add((AlignFrame) sf.getTopFrame());
2502 if (sf.getBottomFrame() instanceof AlignFrame)
2504 avp.add((AlignFrame) sf.getBottomFrame());
2508 if (avp.size() == 0)
2512 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2517 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2521 public GStructureViewer[] getJmols()
2523 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2529 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2531 for (int i = frames.length - 1; i > -1; i--)
2533 if (frames[i] instanceof AppJmol)
2535 GStructureViewer af = (GStructureViewer) frames[i];
2539 if (avp.size() == 0)
2543 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2548 * Add Groovy Support to Jalview
2550 public void groovyShell_actionPerformed()
2554 openGroovyConsole();
2555 } catch (Exception ex)
2557 jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
2558 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2560 MessageManager.getString("label.couldnt_create_groovy_shell"),
2561 MessageManager.getString("label.groovy_support_failed"),
2562 JvOptionPane.ERROR_MESSAGE);
2567 * Open the Groovy console
2569 void openGroovyConsole()
2571 if (groovyConsole == null)
2573 groovyConsole = new groovy.ui.Console();
2574 groovyConsole.setVariable("Jalview", this);
2575 groovyConsole.run();
2578 * We allow only one console at a time, so that AlignFrame menu option
2579 * 'Calculate | Run Groovy script' is unambiguous.
2580 * Disable 'Groovy Console', and enable 'Run script', when the console is
2581 * opened, and the reverse when it is closed
2583 Window window = (Window) groovyConsole.getFrame();
2584 window.addWindowListener(new WindowAdapter()
2587 public void windowClosed(WindowEvent e)
2590 * rebind CMD-Q from Groovy Console to Jalview Quit
2593 enableExecuteGroovy(false);
2599 * show Groovy console window (after close and reopen)
2601 ((Window) groovyConsole.getFrame()).setVisible(true);
2604 * if we got this far, enable 'Run Groovy' in AlignFrame menus
2605 * and disable opening a second console
2607 enableExecuteGroovy(true);
2611 * Bind Ctrl/Cmd-Q to Quit - for reset as Groovy Console takes over this
2612 * binding when opened
2614 protected void addQuitHandler()
2616 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
2617 KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
2618 .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
2619 getRootPane().getActionMap().put("Quit", new AbstractAction()
2622 public void actionPerformed(ActionEvent e)
2630 * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
2633 * true if Groovy console is open
2635 public void enableExecuteGroovy(boolean enabled)
2638 * disable opening a second Groovy console
2639 * (or re-enable when the console is closed)
2641 groovyShell.setEnabled(!enabled);
2643 AlignFrame[] alignFrames = getAlignFrames();
2644 if (alignFrames != null)
2646 for (AlignFrame af : alignFrames)
2648 af.setGroovyEnabled(enabled);
2654 * Progress bars managed by the IProgressIndicator method.
2656 private Hashtable<Long, JPanel> progressBars;
2658 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2663 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2666 public void setProgressBar(String message, long id)
2668 if (progressBars == null)
2670 progressBars = new Hashtable<Long, JPanel>();
2671 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2674 if (progressBars.get(new Long(id)) != null)
2676 JPanel panel = progressBars.remove(new Long(id));
2677 if (progressBarHandlers.contains(new Long(id)))
2679 progressBarHandlers.remove(new Long(id));
2681 removeProgressPanel(panel);
2685 progressBars.put(new Long(id), addProgressPanel(message));
2692 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2693 * jalview.gui.IProgressIndicatorHandler)
2696 public void registerHandler(final long id,
2697 final IProgressIndicatorHandler handler)
2699 if (progressBarHandlers == null
2700 || !progressBars.containsKey(new Long(id)))
2704 .getString("error.call_setprogressbar_before_registering_handler"));
2706 progressBarHandlers.put(new Long(id), handler);
2707 final JPanel progressPanel = progressBars.get(new Long(id));
2708 if (handler.canCancel())
2710 JButton cancel = new JButton(
2711 MessageManager.getString("action.cancel"));
2712 final IProgressIndicator us = this;
2713 cancel.addActionListener(new ActionListener()
2717 public void actionPerformed(ActionEvent e)
2719 handler.cancelActivity(id);
2720 us.setProgressBar(MessageManager.formatMessage(
2721 "label.cancelled_params",
2722 new Object[] { ((JLabel) progressPanel.getComponent(0))
2726 progressPanel.add(cancel, BorderLayout.EAST);
2732 * @return true if any progress bars are still active
2735 public boolean operationInProgress()
2737 if (progressBars != null && progressBars.size() > 0)
2745 * This will return the first AlignFrame holding the given viewport instance.
2746 * It will break if there are more than one AlignFrames viewing a particular
2750 * @return alignFrame for viewport
2752 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2754 if (desktop != null)
2756 AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
2757 for (int panel = 0; aps != null && panel < aps.length; panel++)
2759 if (aps[panel] != null && aps[panel].av == viewport)
2761 return aps[panel].alignFrame;
2768 public VamsasApplication getVamsasApplication()
2775 * flag set if jalview GUI is being operated programmatically
2777 private boolean inBatchMode = false;
2780 * check if jalview GUI is being operated programmatically
2782 * @return inBatchMode
2784 public boolean isInBatchMode()
2790 * set flag if jalview GUI is being operated programmatically
2792 * @param inBatchMode
2794 public void setInBatchMode(boolean inBatchMode)
2796 this.inBatchMode = inBatchMode;
2799 public void startServiceDiscovery()
2801 startServiceDiscovery(false);
2804 public void startServiceDiscovery(boolean blocking)
2806 boolean alive = true;
2807 Thread t0 = null, t1 = null, t2 = null;
2808 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2811 // todo: changesupport handlers need to be transferred
2812 if (discoverer == null)
2814 discoverer = new jalview.ws.jws1.Discoverer();
2815 // register PCS handler for desktop.
2816 discoverer.addPropertyChangeListener(changeSupport);
2818 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2819 // until we phase out completely
2820 (t0 = new Thread(discoverer)).start();
2823 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2825 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2827 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2829 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2835 // TODO: do rest service discovery
2844 } catch (Exception e)
2847 alive = (t1 != null && t1.isAlive())
2848 || (t2 != null && t2.isAlive())
2849 || (t3 != null && t3.isAlive())
2850 || (t0 != null && t0.isAlive());
2856 * called to check if the service discovery process completed successfully.
2860 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2862 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2864 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2865 .getErrorMessages();
2868 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2870 if (serviceChangedDialog == null)
2872 // only run if we aren't already displaying one of these.
2873 addDialogThread(serviceChangedDialog = new Runnable()
2880 * JalviewDialog jd =new JalviewDialog() {
2882 * @Override protected void cancelPressed() { // TODO
2883 * Auto-generated method stub
2885 * }@Override protected void okPressed() { // TODO
2886 * Auto-generated method stub
2888 * }@Override protected void raiseClosed() { // TODO
2889 * Auto-generated method stub
2891 * } }; jd.initDialogFrame(new
2892 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2893 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2894 * + " or mis-configured HTTP proxy settings.<br/>" +
2895 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2897 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2898 * ), true, true, "Web Service Configuration Problem", 450,
2901 * jd.waitForInput();
2907 "<html><table width=\"450\"><tr><td>"
2909 + "</td></tr></table>"
2910 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2911 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2912 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2913 + " Tools->Preferences dialog box to change them.</p></html>"),
2914 "Web Service Configuration Problem",
2915 JvOptionPane.DEFAULT_OPTION,
2916 JvOptionPane.ERROR_MESSAGE);
2917 serviceChangedDialog = null;
2926 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2933 private Runnable serviceChangedDialog = null;
2936 * start a thread to open a URL in the configured browser. Pops up a warning
2937 * dialog to the user if there is an exception when calling out to the browser
2942 public static void showUrl(final String url)
2944 showUrl(url, Desktop.instance);
2948 * Like showUrl but allows progress handler to be specified
2952 * (null) or object implementing IProgressIndicator
2954 public static void showUrl(final String url,
2955 final IProgressIndicator progress)
2957 new Thread(new Runnable()
2964 if (progress != null)
2966 progress.setProgressBar(MessageManager.formatMessage(
2967 "status.opening_params", new Object[] { url }), this
2970 jalview.util.BrowserLauncher.openURL(url);
2971 } catch (Exception ex)
2973 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2975 .getString("label.web_browser_not_found_unix"),
2976 MessageManager.getString("label.web_browser_not_found"),
2977 JvOptionPane.WARNING_MESSAGE);
2979 ex.printStackTrace();
2981 if (progress != null)
2983 progress.setProgressBar(null, this.hashCode());
2989 public static WsParamSetManager wsparamManager = null;
2991 public static ParamManager getUserParameterStore()
2993 if (wsparamManager == null)
2995 wsparamManager = new WsParamSetManager();
2997 return wsparamManager;
3001 * static hyperlink handler proxy method for use by Jalview's internal windows
3005 public static void hyperlinkUpdate(HyperlinkEvent e)
3007 if (e.getEventType() == EventType.ACTIVATED)
3012 url = e.getURL().toString();
3013 Desktop.showUrl(url);
3014 } catch (Exception x)
3018 if (Cache.log != null)
3020 Cache.log.error("Couldn't handle string " + url + " as a URL.");
3024 System.err.println("Couldn't handle string " + url
3028 // ignore any exceptions due to dud links.
3035 * single thread that handles display of dialogs to user.
3037 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
3040 * flag indicating if dialogExecutor should try to acquire a permit
3042 private volatile boolean dialogPause = true;
3047 private java.util.concurrent.Semaphore block = new Semaphore(0);
3049 private static groovy.ui.Console groovyConsole;
3052 * add another dialog thread to the queue
3056 public void addDialogThread(final Runnable prompter)
3058 dialogExecutor.submit(new Runnable()
3068 } catch (InterruptedException x)
3073 if (instance == null)
3079 SwingUtilities.invokeAndWait(prompter);
3080 } catch (Exception q)
3082 Cache.log.warn("Unexpected Exception in dialog thread.", q);
3088 public void startDialogQueue()
3090 // set the flag so we don't pause waiting for another permit and semaphore
3091 // the current task to begin
3092 dialogPause = false;
3097 protected void snapShotWindow_actionPerformed(ActionEvent e)
3101 ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
3102 "View of Desktop", getWidth(), getHeight(), of = new File(
3103 "Jalview_snapshot" + System.currentTimeMillis()
3104 + ".eps"), "View of desktop", null, 0, false);
3107 paintAll(im.getGraphics());
3109 } catch (Exception q)
3111 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
3115 Cache.log.info("Successfully written snapshot to file "
3116 + of.getAbsolutePath());
3120 * Explode the views in the given SplitFrame into separate SplitFrame windows.
3121 * This respects (remembers) any previous 'exploded geometry' i.e. the size
3122 * and location last time the view was expanded (if any). However it does not
3123 * remember the split pane divider location - this is set to match the
3124 * 'exploding' frame.
3128 public void explodeViews(SplitFrame sf)
3130 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
3131 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
3132 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
3134 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
3136 int viewCount = topPanels.size();
3143 * Processing in reverse order works, forwards order leaves the first panels
3144 * not visible. I don't know why!
3146 for (int i = viewCount - 1; i >= 0; i--)
3149 * Make new top and bottom frames. These take over the respective
3150 * AlignmentPanel objects, including their AlignmentViewports, so the
3151 * cdna/protein relationships between the viewports is carried over to the
3154 * explodedGeometry holds the (x, y) position of the previously exploded
3155 * SplitFrame, and the (width, height) of the AlignFrame component
3157 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
3158 AlignFrame newTopFrame = new AlignFrame(topPanel);
3159 newTopFrame.setSize(oldTopFrame.getSize());
3160 newTopFrame.setVisible(true);
3161 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
3162 .getExplodedGeometry();
3163 if (geometry != null)
3165 newTopFrame.setSize(geometry.getSize());
3168 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
3169 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
3170 newBottomFrame.setSize(oldBottomFrame.getSize());
3171 newBottomFrame.setVisible(true);
3172 geometry = ((AlignViewport) bottomPanel.getAlignViewport())
3173 .getExplodedGeometry();
3174 if (geometry != null)
3176 newBottomFrame.setSize(geometry.getSize());
3179 topPanel.av.setGatherViewsHere(false);
3180 bottomPanel.av.setGatherViewsHere(false);
3181 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
3183 if (geometry != null)
3185 splitFrame.setLocation(geometry.getLocation());
3187 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
3191 * Clear references to the panels (now relocated in the new SplitFrames)
3192 * before closing the old SplitFrame.
3195 bottomPanels.clear();
3200 * Gather expanded split frames, sharing the same pairs of sequence set ids,
3201 * back into the given SplitFrame as additional views. Note that the gathered
3202 * frames may themselves have multiple views.
3206 public void gatherViews(GSplitFrame source)
3209 * special handling of explodedGeometry for a view within a SplitFrame: - it
3210 * holds the (x, y) position of the enclosing SplitFrame, and the (width,
3211 * height) of the AlignFrame component
3213 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
3214 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
3215 myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3216 source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
3217 myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
3218 source.getY(), myBottomFrame.getWidth(), myBottomFrame
3220 myTopFrame.viewport.setGatherViewsHere(true);
3221 myBottomFrame.viewport.setGatherViewsHere(true);
3222 String topViewId = myTopFrame.viewport.getSequenceSetId();
3223 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
3225 JInternalFrame[] frames = desktop.getAllFrames();
3226 for (JInternalFrame frame : frames)
3228 if (frame instanceof SplitFrame && frame != source)
3230 SplitFrame sf = (SplitFrame) frame;
3231 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3232 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3233 boolean gatherThis = false;
3234 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3236 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3237 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3238 if (topViewId.equals(topPanel.av.getSequenceSetId())
3239 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3242 topPanel.av.setGatherViewsHere(false);
3243 bottomPanel.av.setGatherViewsHere(false);
3244 topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
3245 topFrame.getSize()));
3246 bottomPanel.av.setExplodedGeometry(new Rectangle(sf
3247 .getLocation(), bottomFrame.getSize()));
3248 myTopFrame.addAlignmentPanel(topPanel, false);
3249 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3255 topFrame.getAlignPanels().clear();
3256 bottomFrame.getAlignPanels().clear();
3263 * The dust settles...give focus to the tab we did this from.
3265 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3268 public static groovy.ui.Console getGroovyConsole()
3270 return groovyConsole;
3273 public static void transferFromDropTarget(List<String> files,
3274 List<DataSourceType> protocols, DropTargetDropEvent evt,
3279 DataFlavor uriListFlavor = new DataFlavor(
3280 "text/uri-list;class=java.lang.String");
3281 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3283 // Works on Windows and MacOSX
3284 Cache.log.debug("Drop handled as javaFileListFlavor");
3285 for (Object file : (List) t
3286 .getTransferData(DataFlavor.javaFileListFlavor))
3288 files.add(((File) file).toString());
3289 protocols.add(DataSourceType.FILE);
3294 // Unix like behaviour
3295 boolean added = false;
3297 if (t.isDataFlavorSupported(uriListFlavor))
3299 Cache.log.debug("Drop handled as uriListFlavor");
3300 // This is used by Unix drag system
3301 data = (String) t.getTransferData(uriListFlavor);
3305 // fallback to text: workaround - on OSX where there's a JVM bug
3306 Cache.log.debug("standard URIListFlavor failed. Trying text");
3307 // try text fallback
3308 data = (String) t.getTransferData(new DataFlavor(
3309 "text/plain;class=java.lang.String"));
3310 if (Cache.log.isDebugEnabled())
3312 Cache.log.debug("fallback returned " + data);
3315 while (protocols.size() < files.size())
3317 Cache.log.debug("Adding missing FILE protocol for "
3318 + files.get(protocols.size()));
3319 protocols.add(DataSourceType.FILE);
3321 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3322 data, "\r\n"); st.hasMoreTokens();)
3325 String s = st.nextToken();
3326 if (s.startsWith("#"))
3328 // the line is a comment (as per the RFC 2483)
3331 java.net.URI uri = new java.net.URI(s);
3332 if (uri.getScheme().toLowerCase().startsWith("http"))
3334 protocols.add(DataSourceType.URL);
3335 files.add(uri.toString());
3339 // otherwise preserve old behaviour: catch all for file objects
3340 java.io.File file = new java.io.File(uri);
3341 protocols.add(DataSourceType.FILE);
3342 files.add(file.toString());
3345 if (Cache.log.isDebugEnabled())
3347 if (data == null || !added)
3350 .debug("Couldn't resolve drop data. Here are the supported flavors:");
3351 for (DataFlavor fl : t.getTransferDataFlavors())
3353 Cache.log.debug("Supported transfer dataflavor: "
3355 Object df = t.getTransferData(fl);
3358 Cache.log.debug("Retrieves: " + df);
3362 Cache.log.debug("Retrieved nothing");