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.api.StructureSelectionManagerProvider;
26 import jalview.bin.Cache;
27 import jalview.io.AppletFormatAdapter;
28 import jalview.io.FileLoader;
29 import jalview.io.FormatAdapter;
30 import jalview.io.IdentifyFile;
31 import jalview.io.JalviewFileChooser;
32 import jalview.io.JalviewFileView;
33 import jalview.jbgui.GDesktop;
34 import jalview.jbgui.GSplitFrame;
35 import jalview.jbgui.GStructureViewer;
36 import jalview.structure.StructureSelectionManager;
37 import jalview.util.BrowserLauncher;
38 import jalview.util.ImageMaker;
39 import jalview.util.MessageManager;
40 import jalview.viewmodel.AlignmentViewport;
41 import jalview.ws.params.ParamManager;
43 import java.awt.BorderLayout;
44 import java.awt.Color;
45 import java.awt.Dimension;
46 import java.awt.FontMetrics;
47 import java.awt.Graphics;
48 import java.awt.GridLayout;
49 import java.awt.Point;
50 import java.awt.Rectangle;
51 import java.awt.Toolkit;
52 import java.awt.datatransfer.Clipboard;
53 import java.awt.datatransfer.ClipboardOwner;
54 import java.awt.datatransfer.DataFlavor;
55 import java.awt.datatransfer.Transferable;
56 import java.awt.dnd.DnDConstants;
57 import java.awt.dnd.DropTargetDragEvent;
58 import java.awt.dnd.DropTargetDropEvent;
59 import java.awt.dnd.DropTargetEvent;
60 import java.awt.dnd.DropTargetListener;
61 import java.awt.event.ActionEvent;
62 import java.awt.event.ActionListener;
63 import java.awt.event.FocusEvent;
64 import java.awt.event.FocusListener;
65 import java.awt.event.MouseAdapter;
66 import java.awt.event.MouseEvent;
67 import java.awt.event.MouseListener;
68 import java.awt.event.WindowAdapter;
69 import java.awt.event.WindowEvent;
70 import java.beans.PropertyChangeEvent;
71 import java.beans.PropertyChangeListener;
72 import java.beans.PropertyVetoException;
73 import java.io.BufferedInputStream;
75 import java.io.FileOutputStream;
76 import java.lang.reflect.Constructor;
78 import java.util.ArrayList;
79 import java.util.Hashtable;
80 import java.util.List;
81 import java.util.StringTokenizer;
82 import java.util.Vector;
83 import java.util.concurrent.ExecutorService;
84 import java.util.concurrent.Executors;
85 import java.util.concurrent.Semaphore;
87 import javax.swing.DefaultDesktopManager;
88 import javax.swing.DesktopManager;
89 import javax.swing.JButton;
90 import javax.swing.JComboBox;
91 import javax.swing.JComponent;
92 import javax.swing.JDesktopPane;
93 import javax.swing.JFrame;
94 import javax.swing.JInternalFrame;
95 import javax.swing.JLabel;
96 import javax.swing.JMenuItem;
97 import javax.swing.JOptionPane;
98 import javax.swing.JPanel;
99 import javax.swing.JPopupMenu;
100 import javax.swing.JProgressBar;
101 import javax.swing.SwingUtilities;
102 import javax.swing.event.HyperlinkEvent;
103 import javax.swing.event.HyperlinkEvent.EventType;
104 import javax.swing.event.MenuEvent;
105 import javax.swing.event.MenuListener;
112 * @version $Revision: 1.155 $
114 public class Desktop extends GDesktop implements
116 ClipboardOwner, IProgressIndicator,
117 StructureSelectionManagerProvider
120 private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
123 * news reader - null if it was never started.
125 private BlogReader jvnews = null;
127 private File projectFile;
131 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener)
133 public void addJalviewPropertyChangeListener(
134 PropertyChangeListener listener)
136 changeSupport.addJalviewPropertyChangeListener(listener);
140 * @param propertyName
142 * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.lang.String,
143 * java.beans.PropertyChangeListener)
145 public void addJalviewPropertyChangeListener(String propertyName,
146 PropertyChangeListener listener)
148 changeSupport.addJalviewPropertyChangeListener(propertyName, listener);
152 * @param propertyName
154 * @see jalview.gui.JalviewChangeSupport#removeJalviewPropertyChangeListener(java.lang.String,
155 * java.beans.PropertyChangeListener)
157 public void removeJalviewPropertyChangeListener(String propertyName,
158 PropertyChangeListener listener)
160 changeSupport.removeJalviewPropertyChangeListener(propertyName,
164 /** Singleton Desktop instance */
165 public static Desktop instance;
167 public static MyDesktopPane desktop;
169 static int openFrameCount = 0;
171 static final int xOffset = 30;
173 static final int yOffset = 30;
175 private static final int THREE = 3;
177 private static AlignFrame currentAlignFrame;
179 public static jalview.ws.jws1.Discoverer discoverer;
181 public static Object[] jalviewClipboard;
183 public static boolean internalCopy = false;
185 static int fileLoadingCount = 0;
187 class MyDesktopManager implements DesktopManager
190 private DesktopManager delegate;
192 public MyDesktopManager(DesktopManager delegate)
194 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);
209 public void beginDraggingFrame(JComponent f)
211 delegate.beginDraggingFrame(f);
214 public void beginResizingFrame(JComponent f, int direction)
216 delegate.beginResizingFrame(f, direction);
219 public void closeFrame(JInternalFrame f)
221 delegate.closeFrame(f);
224 public void deactivateFrame(JInternalFrame f)
226 delegate.deactivateFrame(f);
229 public void deiconifyFrame(JInternalFrame f)
231 delegate.deiconifyFrame(f);
234 public void dragFrame(JComponent f, int newX, int newY)
240 delegate.dragFrame(f, newX, newY);
243 public void endDraggingFrame(JComponent f)
245 delegate.endDraggingFrame(f);
248 public void endResizingFrame(JComponent f)
250 delegate.endResizingFrame(f);
253 public void iconifyFrame(JInternalFrame f)
255 delegate.iconifyFrame(f);
258 public void maximizeFrame(JInternalFrame f)
260 delegate.maximizeFrame(f);
263 public void minimizeFrame(JInternalFrame f)
265 delegate.minimizeFrame(f);
268 public void openFrame(JInternalFrame f)
270 delegate.openFrame(f);
273 public void resizeFrame(JComponent f, int newX, int newY, int newWidth,
276 Rectangle b = desktop.getBounds();
281 delegate.resizeFrame(f, newX, newY, newWidth, newHeight);
284 public void setBoundsForFrame(JComponent f, int newX, int newY,
285 int newWidth, int newHeight)
287 delegate.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
290 // All other methods, simply delegate
295 * Creates a new Desktop object.
300 * A note to implementors. It is ESSENTIAL that any activities that might
301 * block are spawned off as threads rather than waited for during this
305 doVamsasClientCheck();
307 doConfigureStructurePrefs();
308 setTitle("Jalview " + Cache.getProperty("VERSION"));
309 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
310 boolean selmemusage = Cache.getDefault("SHOW_MEMUSAGE",
312 boolean showjconsole = Cache.getDefault(
313 "SHOW_JAVA_CONSOLE", false);
314 desktop = new MyDesktopPane(selmemusage);
315 showMemusage.setSelected(selmemusage);
316 desktop.setBackground(Color.white);
317 getContentPane().setLayout(new BorderLayout());
318 // alternate config - have scrollbars - see notes in JAL-153
319 // JScrollPane sp = new JScrollPane();
320 // sp.getViewport().setView(desktop);
321 // getContentPane().add(sp, BorderLayout.CENTER);
322 getContentPane().add(desktop, BorderLayout.CENTER);
323 desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
325 // This line prevents Windows Look&Feel resizing all new windows to maximum
326 // if previous window was maximised
327 desktop.setDesktopManager(new MyDesktopManager(
328 new DefaultDesktopManager()));
330 Rectangle dims = getLastKnownDimensions("");
337 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
338 setBounds((screenSize.width - 900) / 2,
339 (screenSize.height - 650) / 2, 900, 650);
341 jconsole = new Console(this, showjconsole);
342 // add essential build information
343 jconsole.setHeader("Jalview Version: "
344 + Cache.getProperty("VERSION") + "\n"
345 + "Jalview Installation: "
346 + Cache.getDefault("INSTALLATION", "unknown")
347 + "\n" + "Build Date: "
348 + Cache.getDefault("BUILD_DATE", "unknown") + "\n"
349 + "Java version: " + System.getProperty("java.version") + "\n"
350 + System.getProperty("os.arch") + " "
351 + System.getProperty("os.name") + " "
352 + System.getProperty("os.version"));
354 showConsole(showjconsole);
356 showNews.setVisible(false);
358 this.addWindowListener(new WindowAdapter()
360 public void windowClosing(WindowEvent evt)
367 this.addMouseListener(ma = new MouseAdapter()
369 public void mousePressed(MouseEvent evt)
371 if (SwingUtilities.isRightMouseButton(evt))
373 showPasteMenu(evt.getX(), evt.getY());
377 desktop.addMouseListener(ma);
379 this.addFocusListener(new FocusListener()
383 public void focusLost(FocusEvent e)
385 // TODO Auto-generated method stub
390 public void focusGained(FocusEvent e)
392 Cache.log.debug("Relaying windows after focus gain");
393 // make sure that we sort windows properly after we gain focus
394 instance.relayerWindows();
397 this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
398 // Spawn a thread that shows the splashscreen
399 SwingUtilities.invokeLater(new Runnable()
408 // Thread off a new instance of the file chooser - this reduces the time it
409 // takes to open it later on.
410 new Thread(new Runnable()
414 Cache.log.debug("Filechooser init thread started.");
415 JalviewFileChooser chooser = new JalviewFileChooser(
416 Cache.getProperty("LAST_DIRECTORY"),
417 AppletFormatAdapter.READABLE_EXTENSIONS,
418 AppletFormatAdapter.READABLE_FNAMES,
419 Cache.getProperty("DEFAULT_FILE_FORMAT"));
420 Cache.log.debug("Filechooser init thread finished.");
423 // Add the service change listener
424 changeSupport.addJalviewPropertyChangeListener("services",
425 new PropertyChangeListener()
429 public void propertyChange(PropertyChangeEvent evt)
431 Cache.log.debug("Firing service changed event for "
432 + evt.getNewValue());
433 JalviewServicesChanged(evt);
439 public void doConfigureStructurePrefs()
441 // configure services
442 StructureSelectionManager ssm = StructureSelectionManager
443 .getStructureSelectionManager(this);
444 if (Cache.getDefault(Preferences.ADD_SS_ANN, true))
446 ssm.setAddTempFacAnnot(Cache.getDefault(
447 Preferences.ADD_TEMPFACT_ANN, true));
448 ssm.setProcessSecondaryStructure(Cache.getDefault(
449 Preferences.STRUCT_FROM_PDB, true));
450 ssm.setSecStructServices(Cache.getDefault(
451 Preferences.USE_RNAVIEW, true));
455 ssm.setAddTempFacAnnot(false);
456 ssm.setProcessSecondaryStructure(false);
457 ssm.setSecStructServices(false);
461 public void checkForNews()
463 final Desktop me = this;
464 // Thread off the news reader, in case there are connection problems.
465 addDialogThread(new Runnable()
470 Cache.log.debug("Starting news thread.");
472 jvnews = new BlogReader(me);
473 showNews.setVisible(true);
474 Cache.log.debug("Completed news thread.");
479 protected void showNews_actionPerformed(ActionEvent e)
481 showNews(showNews.isSelected());
484 void showNews(boolean visible)
487 Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
488 showNews.setSelected(visible);
489 if (visible && !jvnews.isVisible())
491 new Thread(new Runnable()
496 long instance = System.currentTimeMillis();
497 Desktop.instance.setProgressBar(
498 MessageManager.getString("status.refreshing_news"),
500 jvnews.refreshNews();
501 Desktop.instance.setProgressBar(null, instance);
510 * recover the last known dimensions for a jalview window
513 * - empty string is desktop, all other windows have unique prefix
514 * @return null or last known dimensions scaled to current geometry (if last
515 * window geom was known)
517 Rectangle getLastKnownDimensions(String windowName)
519 // TODO: lock aspect ratio for scaling desktop Bug #0058199
520 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
521 String x = Cache.getProperty(windowName + "SCREEN_X");
522 String y = Cache.getProperty(windowName + "SCREEN_Y");
523 String width = Cache.getProperty(windowName
525 String height = Cache.getProperty(windowName
527 if ((x != null) && (y != null) && (width != null) && (height != null))
529 int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
530 .parseInt(width), ih = Integer.parseInt(height);
531 if (Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
533 // attempt #1 - try to cope with change in screen geometry - this
534 // version doesn't preserve original jv aspect ratio.
535 // take ratio of current screen size vs original screen size.
536 double sw = ((1f * screenSize.width) / (1f * Integer
538 .getProperty("SCREENGEOMETRY_WIDTH"))));
539 double sh = ((1f * screenSize.height) / (1f * Integer
541 .getProperty("SCREENGEOMETRY_HEIGHT"))));
542 // rescale the bounds depending upon the current screen geometry.
543 ix = (int) (ix * sw);
544 iw = (int) (iw * sw);
545 iy = (int) (iy * sh);
546 ih = (int) (ih * sh);
547 while (ix >= screenSize.width)
550 .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
551 ix -= screenSize.width;
553 while (iy >= screenSize.height)
556 .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
557 iy -= screenSize.height;
559 Cache.log.debug("Got last known dimensions for "
560 + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
563 // return dimensions for new instance
564 return new Rectangle(ix, iy, iw, ih);
569 private void doVamsasClientCheck()
571 if (Cache.vamsasJarsPresent())
573 setupVamsasDisconnectedGui();
574 VamsasMenu.setVisible(true);
575 final Desktop us = this;
576 VamsasMenu.addMenuListener(new MenuListener()
578 // this listener remembers when the menu was first selected, and
579 // doesn't rebuild the session list until it has been cleared and
581 boolean refresh = true;
583 public void menuCanceled(MenuEvent e)
588 public void menuDeselected(MenuEvent e)
593 public void menuSelected(MenuEvent e)
597 us.buildVamsasStMenu();
602 vamsasStart.setVisible(true);
606 void showPasteMenu(int x, int y)
608 JPopupMenu popup = new JPopupMenu();
609 JMenuItem item = new JMenuItem(
610 MessageManager.getString("label.paste_new_window"));
611 item.addActionListener(new ActionListener()
613 public void actionPerformed(ActionEvent evt)
620 popup.show(this, x, y);
627 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
628 Transferable contents = c.getContents(this);
630 if (contents != null)
632 String file = (String) contents
633 .getTransferData(DataFlavor.stringFlavor);
635 String format = new IdentifyFile().Identify(file,
636 FormatAdapter.PASTE);
638 new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
641 } catch (Exception ex)
644 .println("Unable to paste alignment from system clipboard:\n"
650 * Adds and opens the given frame to the desktop
661 public static synchronized void addInternalFrame(
662 final JInternalFrame frame, String title, int w, int h)
664 addInternalFrame(frame, title, true, w, h, true);
668 * Add an internal frame to the Jalview desktop
675 * When true, display frame immediately, otherwise, caller must call
676 * setVisible themselves.
682 public static synchronized void addInternalFrame(
683 final JInternalFrame frame, String title, boolean makeVisible,
686 addInternalFrame(frame, title, makeVisible, w, h, true);
690 * Add an internal frame to the Jalview desktop and make it visible
703 public static synchronized void addInternalFrame(
704 final JInternalFrame frame, String title, int w, int h,
707 addInternalFrame(frame, title, true, w, h, resizable);
711 * Add an internal frame to the Jalview desktop
718 * When true, display frame immediately, otherwise, caller must call
719 * setVisible themselves.
727 public static synchronized void addInternalFrame(
728 final JInternalFrame frame, String title, boolean makeVisible,
729 int w, int h, boolean resizable)
732 // TODO: allow callers to determine X and Y position of frame (eg. via
734 // TODO: consider fixing method to update entries in the window submenu with
735 // the current window title
737 frame.setTitle(title);
738 if (frame.getWidth() < 1 || frame.getHeight() < 1)
742 // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
743 // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
744 // IF JALVIEW IS RUNNING HEADLESS
745 // ///////////////////////////////////////////////
747 || (System.getProperty("java.awt.headless") != null && System
748 .getProperty("java.awt.headless").equals("true")))
755 frame.setVisible(makeVisible);
756 frame.setClosable(true);
757 frame.setResizable(resizable);
758 frame.setMaximizable(resizable);
759 frame.setIconifiable(resizable);
760 frame.setFrameIcon(null);
762 if (frame.getX() < 1 && frame.getY() < 1)
764 frame.setLocation(xOffset * openFrameCount, yOffset
765 * ((openFrameCount - 1) % 10) + yOffset);
768 final JMenuItem menuItem = new JMenuItem(title);
769 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
771 public void internalFrameActivated(
772 javax.swing.event.InternalFrameEvent evt)
774 JInternalFrame itf = desktop.getSelectedFrame();
782 public void internalFrameClosed(
783 javax.swing.event.InternalFrameEvent evt)
785 PaintRefresher.RemoveComponent(frame);
787 windowMenu.remove(menuItem);
788 JInternalFrame itf = desktop.getSelectedFrame();
797 menuItem.addActionListener(new ActionListener()
799 public void actionPerformed(ActionEvent e)
803 frame.setSelected(true);
804 frame.setIcon(false);
805 } catch (java.beans.PropertyVetoException ex)
811 menuItem.addMouseListener(new MouseListener()
815 public void mouseReleased(MouseEvent e)
820 public void mousePressed(MouseEvent e)
825 public void mouseExited(MouseEvent e)
829 frame.setSelected(false);
830 } catch (PropertyVetoException e1)
836 public void mouseEntered(MouseEvent e)
840 frame.setSelected(true);
841 } catch (PropertyVetoException e1)
847 public void mouseClicked(MouseEvent e)
853 windowMenu.add(menuItem);
859 frame.setSelected(true);
860 frame.requestFocus();
861 } catch (java.beans.PropertyVetoException ve)
863 } catch (java.lang.ClassCastException cex)
866 .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
871 public void lostOwnership(Clipboard clipboard, Transferable contents)
875 Desktop.jalviewClipboard = null;
878 internalCopy = false;
881 public void dragEnter(DropTargetDragEvent evt)
885 public void dragExit(DropTargetEvent evt)
889 public void dragOver(DropTargetDragEvent evt)
893 public void dropActionChanged(DropTargetDragEvent evt)
903 public void drop(DropTargetDropEvent evt)
905 boolean success = true;
906 Transferable t = evt.getTransferable();
907 java.util.List files = null;
908 java.util.List protocols = null;
912 DataFlavor uriListFlavor = new DataFlavor(
913 "text/uri-list;class=java.lang.String");
914 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
916 // Works on Windows and MacOSX
917 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
918 files = (java.util.List) t
919 .getTransferData(DataFlavor.javaFileListFlavor);
921 else if (t.isDataFlavorSupported(uriListFlavor))
923 // This is used by Unix drag system
924 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
925 String data = (String) t.getTransferData(uriListFlavor);
926 files = new java.util.ArrayList(1);
927 protocols = new java.util.ArrayList(1);
928 for (java.util.StringTokenizer st = new java.util.StringTokenizer(
929 data, "\r\n"); st.hasMoreTokens();)
931 String s = st.nextToken();
932 if (s.startsWith("#"))
934 // the line is a comment (as per the RFC 2483)
937 java.net.URI uri = new java.net.URI(s);
938 if (uri.getScheme().toLowerCase().startsWith("http"))
940 protocols.add(FormatAdapter.URL);
941 files.add(uri.toString());
945 // otherwise preserve old behaviour: catch all for file objects
946 java.io.File file = new java.io.File(uri);
947 protocols.add(FormatAdapter.FILE);
948 files.add(file.toString());
952 } catch (Exception e)
961 for (int i = 0; i < files.size(); i++)
963 String file = files.get(i).toString();
964 String protocol = (protocols == null) ? FormatAdapter.FILE
965 : (String) protocols.get(i);
966 String format = null;
968 if (file.endsWith(".jar"))
975 format = new IdentifyFile().Identify(file, protocol);
978 new FileLoader().LoadFile(file, protocol, format);
981 } catch (Exception ex)
986 evt.dropComplete(success); // need this to ensure input focus is properly
987 // transfered to any new windows created
996 public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
998 JalviewFileChooser chooser = new JalviewFileChooser(
999 Cache.getProperty("LAST_DIRECTORY"),
1000 AppletFormatAdapter.READABLE_EXTENSIONS,
1001 AppletFormatAdapter.READABLE_FNAMES,
1002 Cache.getProperty("DEFAULT_FILE_FORMAT"));
1004 chooser.setFileView(new JalviewFileView());
1005 chooser.setDialogTitle(MessageManager
1006 .getString("label.open_local_file"));
1007 chooser.setToolTipText(MessageManager.getString("action.open"));
1009 int value = chooser.showOpenDialog(this);
1011 if (value == JalviewFileChooser.APPROVE_OPTION)
1013 String choice = chooser.getSelectedFile().getPath();
1014 Cache.setProperty("LAST_DIRECTORY", chooser
1015 .getSelectedFile().getParent());
1017 String format = null;
1018 if (chooser.getSelectedFormat() != null
1019 && chooser.getSelectedFormat().equals("Jalview"))
1025 format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
1028 if (viewport != null)
1030 new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
1032 // viewport.setShowSequenceFeatures(JSONFile.isSeqFeaturesEnabled());
1033 // AlignFrame af = viewport.getAlignPanel().alignFrame;
1036 // af.changeColour(JSONFile.getColourScheme());
1037 // af.setMenusForViewport();
1042 new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
1053 public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
1055 // This construct allows us to have a wider textfield
1057 JLabel label = new JLabel(
1058 MessageManager.getString("label.input_file_url"));
1059 final JComboBox history = new JComboBox();
1061 JPanel panel = new JPanel(new GridLayout(2, 1));
1064 history.setPreferredSize(new Dimension(400, 20));
1065 history.setEditable(true);
1066 history.addItem("http://www.");
1068 String historyItems = Cache.getProperty("RECENT_URL");
1072 if (historyItems != null)
1074 st = new StringTokenizer(historyItems, "\t");
1076 while (st.hasMoreTokens())
1078 history.addItem(st.nextElement());
1082 int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
1083 MessageManager.getString("label.input_alignment_from_url"),
1084 JOptionPane.OK_CANCEL_OPTION);
1086 if (reply != JOptionPane.OK_OPTION)
1091 String url = history.getSelectedItem().toString();
1093 if (url.toLowerCase().endsWith(".jar"))
1095 if (viewport != null)
1097 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
1102 new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
1107 String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
1109 if (format.equals("URL NOT FOUND"))
1111 JOptionPane.showInternalMessageDialog(Desktop.desktop,
1112 MessageManager.formatMessage("label.couldnt_locate",
1114 { url }), MessageManager
1115 .getString("label.url_not_found"),
1116 JOptionPane.WARNING_MESSAGE);
1121 if (viewport != null)
1123 new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
1127 new FileLoader().LoadFile(url, FormatAdapter.URL, format);
1138 public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
1140 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1141 // cap.setForInput(viewport.getAlignPanel());
1142 cap.setForInput(null);
1143 Desktop.addInternalFrame(cap,
1144 MessageManager.getString("label.cut_paste_alignmen_file"),
1153 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1155 .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
1156 Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
1158 storeLastKnownDimensions("", new Rectangle(getBounds().x,
1159 getBounds().y, getWidth(), getHeight()));
1161 if (jconsole != null)
1163 storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
1164 jconsole.stopConsole();
1168 storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
1171 if (dialogExecutor != null)
1173 dialogExecutor.shutdownNow();
1175 closeAll_actionPerformed(null);
1179 private void storeLastKnownDimensions(String string, Rectangle jc)
1181 Cache.log.debug("Storing last known dimensions for "
1182 + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width
1183 + " height:" + jc.height);
1185 Cache.setProperty(string + "SCREEN_X", jc.x + "");
1186 Cache.setProperty(string + "SCREEN_Y", jc.y + "");
1187 Cache.setProperty(string + "SCREEN_WIDTH", jc.width + "");
1188 Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + "");
1197 public void aboutMenuItem_actionPerformed(ActionEvent e)
1199 // StringBuffer message = getAboutMessage(false);
1200 // JOptionPane.showInternalMessageDialog(Desktop.desktop,
1202 // message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
1203 new Thread(new Runnable()
1207 new SplashScreen(true);
1212 public StringBuffer getAboutMessage(boolean shortv)
1214 StringBuffer message = new StringBuffer();
1215 message.append("<html>");
1218 message.append("<h1><strong>Version: "
1219 + Cache.getProperty("VERSION") + "</strong></h1>");
1220 message.append("<strong>Last Updated: <em>"
1221 + Cache.getDefault("BUILD_DATE", "unknown")
1222 + "</em></strong>");
1228 message.append("<strong>Version "
1229 + Cache.getProperty("VERSION")
1230 + "; last updated: "
1231 + Cache.getDefault("BUILD_DATE", "unknown"));
1234 if (Cache.getDefault("LATEST_VERSION", "Checking").equals(
1237 message.append("<br>...Checking latest version...</br>");
1239 else if (!Cache.getDefault("LATEST_VERSION", "Checking")
1240 .equals(Cache.getProperty("VERSION")))
1242 boolean red = false;
1243 if (Cache.getProperty("VERSION").toLowerCase()
1244 .indexOf("automated build") == -1)
1247 // Displayed when code version and jnlp version do not match and code
1248 // version is not a development build
1249 message.append("<div style=\"color: #FF0000;font-style: bold;\">");
1252 message.append("<br>!! Version "
1253 + Cache.getDefault("LATEST_VERSION",
1255 + " is available for download from "
1256 + Cache.getDefault("www.jalview.org",
1257 "http://www.jalview.org") + " !!");
1260 message.append("</div>");
1263 message.append("<br>Authors: "
1265 .getDefault("AUTHORFNAMES",
1266 "The Jalview Authors (See AUTHORS file for current list)")
1267 + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
1268 + "<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"
1269 + "<br><br>If you use Jalview, please cite:"
1270 + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
1271 + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
1272 + "<br>Bioinformatics doi: 10.1093/bioinformatics/btp033"
1283 public void documentationMenuItem_actionPerformed(ActionEvent e)
1287 Help.showHelpWindow();
1288 } catch (Exception ex)
1293 public void closeAll_actionPerformed(ActionEvent e)
1295 JInternalFrame[] frames = desktop.getAllFrames();
1296 for (int i = 0; i < frames.length; i++)
1300 frames[i].setClosed(true);
1301 } catch (java.beans.PropertyVetoException ex)
1305 System.out.println("ALL CLOSED");
1306 if (v_client != null)
1308 // TODO clear binding to vamsas document objects on close_all
1313 public void raiseRelated_actionPerformed(ActionEvent e)
1315 reorderAssociatedWindows(false, false);
1318 public void minimizeAssociated_actionPerformed(ActionEvent e)
1320 reorderAssociatedWindows(true, false);
1323 void closeAssociatedWindows()
1325 reorderAssociatedWindows(false, true);
1331 * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
1334 protected void garbageCollect_actionPerformed(ActionEvent e)
1336 // We simply collect the garbage
1337 Cache.log.debug("Collecting garbage...");
1339 Cache.log.debug("Finished garbage collection.");
1346 * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
1349 protected void showMemusage_actionPerformed(ActionEvent e)
1351 desktop.showMemoryUsage(showMemusage.isSelected());
1358 * jalview.jbgui.GDesktop#showConsole_actionPerformed(java.awt.event.ActionEvent
1361 protected void showConsole_actionPerformed(ActionEvent e)
1363 showConsole(showConsole.isSelected());
1366 Console jconsole = null;
1369 * control whether the java console is visible or not
1373 void showConsole(boolean selected)
1375 showConsole.setSelected(selected);
1376 // TODO: decide if we should update properties file
1377 Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
1379 jconsole.setVisible(selected);
1382 void reorderAssociatedWindows(boolean minimize, boolean close)
1384 JInternalFrame[] frames = desktop.getAllFrames();
1385 if (frames == null || frames.length < 1)
1390 AlignmentViewport source = null, target = null;
1391 if (frames[0] instanceof AlignFrame)
1393 source = ((AlignFrame) frames[0]).getCurrentView();
1395 else if (frames[0] instanceof TreePanel)
1397 source = ((TreePanel) frames[0]).getViewPort();
1399 else if (frames[0] instanceof PCAPanel)
1401 source = ((PCAPanel) frames[0]).av;
1403 else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
1405 source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
1410 for (int i = 0; i < frames.length; i++)
1413 if (frames[i] == null)
1417 if (frames[i] instanceof AlignFrame)
1419 target = ((AlignFrame) frames[i]).getCurrentView();
1421 else if (frames[i] instanceof TreePanel)
1423 target = ((TreePanel) frames[i]).getViewPort();
1425 else if (frames[i] instanceof PCAPanel)
1427 target = ((PCAPanel) frames[i]).av;
1429 else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
1431 target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
1434 if (source == target)
1440 frames[i].setClosed(true);
1444 frames[i].setIcon(minimize);
1447 frames[i].toFront();
1451 } catch (java.beans.PropertyVetoException ex)
1465 protected void preferences_actionPerformed(ActionEvent e)
1476 public void saveState_actionPerformed(ActionEvent e)
1478 JalviewFileChooser chooser = new JalviewFileChooser(
1479 Cache.getProperty("LAST_DIRECTORY"), new String[]
1480 { "jvp" }, new String[]
1481 { "Jalview Project" }, "Jalview Project");
1483 chooser.setFileView(new JalviewFileView());
1484 chooser.setDialogTitle(MessageManager.getString("label.save_state"));
1486 int value = chooser.showSaveDialog(this);
1488 if (value == JalviewFileChooser.APPROVE_OPTION)
1490 final Desktop me = this;
1491 final java.io.File choice = chooser.getSelectedFile();
1492 setProjectFile(choice);
1494 new Thread(new Runnable()
1499 setProgressBar(MessageManager.formatMessage(
1500 "label.saving_jalview_project", new Object[]
1501 { choice.getName() }), choice.hashCode());
1502 Cache.setProperty("LAST_DIRECTORY",
1503 choice.getParent());
1504 // TODO catch and handle errors for savestate
1505 // TODO prevent user from messing with the Desktop whilst we're saving
1508 new Jalview2XML().saveState(choice);
1509 } catch (OutOfMemoryError oom)
1511 new OOMWarning("Whilst saving current state to "
1512 + choice.getName(), oom);
1513 } catch (Exception ex)
1516 "Problems whilst trying to save to " + choice.getName(),
1518 JOptionPane.showMessageDialog(me, MessageManager.formatMessage(
1519 "label.error_whilst_saving_current_state_to",
1521 { choice.getName() }), MessageManager
1522 .getString("label.couldnt_save_project"),
1523 JOptionPane.WARNING_MESSAGE);
1525 setProgressBar(null, choice.hashCode());
1531 private void setProjectFile(File choice)
1533 this.projectFile = choice;
1536 public File getProjectFile()
1538 return this.projectFile;
1547 public void loadState_actionPerformed(ActionEvent e)
1549 JalviewFileChooser chooser = new JalviewFileChooser(
1550 Cache.getProperty("LAST_DIRECTORY"), new String[]
1551 { "jvp", "jar" }, new String[]
1552 { "Jalview Project", "Jalview Project (old)" },
1554 chooser.setFileView(new JalviewFileView());
1555 chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
1557 int value = chooser.showOpenDialog(this);
1559 if (value == JalviewFileChooser.APPROVE_OPTION)
1561 final File selectedFile = chooser.getSelectedFile();
1562 setProjectFile(selectedFile);
1563 final String choice = selectedFile.getAbsolutePath();
1564 Cache.setProperty("LAST_DIRECTORY",
1565 selectedFile.getParent());
1566 new Thread(new Runnable()
1570 setProgressBar(MessageManager.formatMessage(
1571 "label.loading_jalview_project", new Object[]
1572 { choice }), choice.hashCode());
1575 new Jalview2XML().loadJalviewAlign(choice);
1576 } catch (OutOfMemoryError oom)
1578 new OOMWarning("Whilst loading project from " + choice, oom);
1579 } catch (Exception ex)
1581 Cache.log.error("Problems whilst loading project from "
1583 JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
1585 "label.error_whilst_loading_project_from",
1587 { choice }), MessageManager
1588 .getString("label.couldnt_load_project"),
1589 JOptionPane.WARNING_MESSAGE);
1591 setProgressBar(null, choice.hashCode());
1597 public void inputSequence_actionPerformed(ActionEvent e)
1599 new SequenceFetcher(this);
1602 JPanel progressPanel;
1604 ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
1606 public void startLoading(final String fileName)
1608 if (fileLoadingCount == 0)
1610 fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
1611 "label.loading_file", new Object[]
1617 private JPanel addProgressPanel(String string)
1619 if (progressPanel == null)
1621 progressPanel = new JPanel(new GridLayout(1, 1));
1622 totalProgressCount = 0;
1623 instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
1625 JPanel thisprogress = new JPanel(new BorderLayout(10, 5));
1626 JProgressBar progressBar = new JProgressBar();
1627 progressBar.setIndeterminate(true);
1629 thisprogress.add(new JLabel(string), BorderLayout.WEST);
1631 thisprogress.add(progressBar, BorderLayout.CENTER);
1632 progressPanel.add(thisprogress);
1633 ((GridLayout) progressPanel.getLayout())
1634 .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
1635 ++totalProgressCount;
1636 instance.validate();
1637 return thisprogress;
1640 int totalProgressCount = 0;
1642 private void removeProgressPanel(JPanel progbar)
1644 if (progressPanel != null)
1646 synchronized (progressPanel)
1648 progressPanel.remove(progbar);
1649 GridLayout gl = (GridLayout) progressPanel.getLayout();
1650 gl.setRows(gl.getRows() - 1);
1651 if (--totalProgressCount < 1)
1653 this.getContentPane().remove(progressPanel);
1654 progressPanel = null;
1661 public void stopLoading()
1664 if (fileLoadingCount < 1)
1666 while (fileLoadingPanels.size() > 0)
1668 removeProgressPanel(fileLoadingPanels.remove(0));
1670 fileLoadingPanels.clear();
1671 fileLoadingCount = 0;
1676 public static int getViewCount(String alignmentId)
1678 AlignmentViewport[] aps = getViewports(alignmentId);
1679 return (aps == null) ? 0 : aps.length;
1684 * @param alignmentId
1685 * - if null, all sets are returned
1686 * @return all AlignmentPanels concerning the alignmentId sequence set
1688 public static AlignmentPanel[] getAlignmentPanels(String alignmentId)
1690 if (Desktop.desktop == null)
1692 // no frames created and in headless mode
1693 // TODO: verify that frames are recoverable when in headless mode
1696 List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
1697 AlignFrame[] frames = getAlignFrames();
1702 for (AlignFrame af : frames)
1704 for (AlignmentPanel ap : af.alignPanels)
1706 if (alignmentId==null || alignmentId.equals(ap.av.getSequenceSetId()))
1712 if (aps.size() == 0)
1716 AlignmentPanel[] vap = aps.toArray(new AlignmentPanel[aps.size()]);
1721 * get all the viewports on an alignment.
1723 * @param sequenceSetId
1724 * unique alignment id (may be null - all viewports returned in that
1726 * @return all viewports on the alignment bound to sequenceSetId
1728 public static AlignmentViewport[] getViewports(String sequenceSetId)
1730 List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
1731 if (desktop != null)
1733 AlignFrame[] frames = Desktop.getAlignFrames();
1735 for (AlignFrame afr : frames)
1737 if (sequenceSetId==null || afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1739 if (afr.alignPanels != null)
1741 for (AlignmentPanel ap : afr.alignPanels)
1743 if (sequenceSetId == null
1744 || sequenceSetId.equals(ap.av.getSequenceSetId()))
1752 viewp.add(afr.getViewport());
1756 if (viewp.size() > 0)
1758 return viewp.toArray(new AlignmentViewport[viewp.size()]);
1765 * Explode the views in the given frame into separate AlignFrame
1769 public void explodeViews(AlignFrame af)
1771 int size = af.alignPanels.size();
1777 for (int i = 0; i < size; i++)
1779 AlignmentPanel ap = af.alignPanels.get(i);
1780 AlignFrame newaf = new AlignFrame(ap);
1783 * Restore the view's last exploded frame geometry if known. Multiple
1784 * views from one exploded frame share and restore the same (frame)
1785 * position and size.
1787 Rectangle geometry = ap.av.getExplodedGeometry();
1788 if (geometry != null)
1790 newaf.setBounds(geometry);
1793 ap.av.setGatherViewsHere(false);
1795 addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1796 AlignFrame.DEFAULT_HEIGHT);
1799 af.alignPanels.clear();
1800 af.closeMenuItem_actionPerformed(true);
1805 * Gather expanded views (separate AlignFrame's) with the same sequence set
1806 * identifier back in to this frame as additional views, and close the
1807 * expanded views. Note the expanded frames may themselves have multiple
1808 * views. We take the lot.
1812 public void gatherViews(AlignFrame source)
1814 source.viewport.setGatherViewsHere(true);
1815 source.viewport.setExplodedGeometry(source.getBounds());
1816 JInternalFrame[] frames = desktop.getAllFrames();
1817 String viewId = source.viewport.getSequenceSetId();
1819 for (int t = 0; t < frames.length; t++)
1821 if (frames[t] instanceof AlignFrame && frames[t] != source)
1823 AlignFrame af = (AlignFrame) frames[t];
1824 boolean gatherThis = false;
1825 for (int a = 0; a < af.alignPanels.size(); a++)
1827 AlignmentPanel ap = af.alignPanels.get(a);
1828 if (viewId.equals(ap.av.getSequenceSetId()))
1831 ap.av.setGatherViewsHere(false);
1832 ap.av.setExplodedGeometry(af.getBounds());
1833 source.addAlignmentPanel(ap, false);
1839 af.alignPanels.clear();
1840 af.closeMenuItem_actionPerformed(true);
1847 VamsasApplication v_client = null;
1849 public void vamsasImport_actionPerformed(ActionEvent e)
1851 if (v_client == null)
1853 // Load and try to start a session.
1854 JalviewFileChooser chooser = new JalviewFileChooser(
1855 Cache.getProperty("LAST_DIRECTORY"));
1857 chooser.setFileView(new JalviewFileView());
1858 chooser.setDialogTitle(MessageManager
1859 .getString("label.open_saved_vamsas_session"));
1860 chooser.setToolTipText(MessageManager
1861 .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
1863 int value = chooser.showOpenDialog(this);
1865 if (value == JalviewFileChooser.APPROVE_OPTION)
1867 String fle = chooser.getSelectedFile().toString();
1868 if (!vamsasImport(chooser.getSelectedFile()))
1871 .showInternalMessageDialog(
1873 MessageManager.formatMessage(
1874 "label.couldnt_import_as_vamsas_session",
1878 .getString("label.vamsas_document_import_failed"),
1879 JOptionPane.ERROR_MESSAGE);
1886 .error("Implementation error - load session from a running session is not supported.");
1891 * import file into a new vamsas session (uses VamsasApplication)
1894 * @return true if import was a success and a session was started.
1896 public boolean vamsasImport(URL url)
1898 // TODO: create progress bar
1899 if (v_client != null)
1903 .error("Implementation error - load session from a running session is not supported.");
1909 // copy the URL content to a temporary local file
1910 // TODO: be a bit cleverer here with nio (?!)
1911 File file = File.createTempFile("vdocfromurl", ".vdj");
1912 FileOutputStream fos = new FileOutputStream(file);
1913 BufferedInputStream bis = new BufferedInputStream(url.openStream());
1914 byte[] buffer = new byte[2048];
1916 while ((ln = bis.read(buffer)) > -1)
1918 fos.write(buffer, 0, ln);
1922 v_client = new VamsasApplication(this, file,
1923 url.toExternalForm());
1924 } catch (Exception ex)
1927 "Failed to create new vamsas session from contents of URL "
1931 setupVamsasConnectedGui();
1932 v_client.initial_update(); // TODO: thread ?
1933 return v_client.inSession();
1937 * import file into a new vamsas session (uses VamsasApplication)
1940 * @return true if import was a success and a session was started.
1942 public boolean vamsasImport(File file)
1944 if (v_client != null)
1948 .error("Implementation error - load session from a running session is not supported.");
1952 setProgressBar(MessageManager.formatMessage(
1953 "status.importing_vamsas_session_from", new Object[]
1954 { file.getName() }), file.hashCode());
1957 v_client = new VamsasApplication(this, file, null);
1958 } catch (Exception ex)
1960 setProgressBar(MessageManager.formatMessage(
1961 "status.importing_vamsas_session_from", new Object[]
1962 { file.getName() }), file.hashCode());
1964 "New vamsas session from existing session file failed:", ex);
1967 setupVamsasConnectedGui();
1968 v_client.initial_update(); // TODO: thread ?
1969 setProgressBar(MessageManager.formatMessage(
1970 "status.importing_vamsas_session_from", new Object[]
1971 { file.getName() }), file.hashCode());
1972 return v_client.inSession();
1975 public boolean joinVamsasSession(String mysesid)
1977 if (v_client != null)
1981 .getString("error.try_join_vamsas_session_another"));
1983 if (mysesid == null)
1986 MessageManager.getString("error.invalid_vamsas_session_id"));
1988 v_client = new VamsasApplication(this, mysesid);
1989 setupVamsasConnectedGui();
1990 v_client.initial_update();
1991 return (v_client.inSession());
1994 public void vamsasStart_actionPerformed(ActionEvent e)
1996 if (v_client == null)
1999 // we just start a default session for moment.
2001 * JalviewFileChooser chooser = new JalviewFileChooser(Cache.
2002 * getProperty("LAST_DIRECTORY"));
2004 * chooser.setFileView(new JalviewFileView());
2005 * chooser.setDialogTitle("Load Vamsas file");
2006 * chooser.setToolTipText("Import");
2008 * int value = chooser.showOpenDialog(this);
2010 * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
2011 * VamsasApplication(this, chooser.getSelectedFile());
2013 v_client = new VamsasApplication(this);
2014 setupVamsasConnectedGui();
2015 v_client.initial_update(); // TODO: thread ?
2019 // store current data in session.
2020 v_client.push_update(); // TODO: thread
2024 protected void setupVamsasConnectedGui()
2026 vamsasStart.setText(MessageManager.getString("label.session_update"));
2027 vamsasSave.setVisible(true);
2028 vamsasStop.setVisible(true);
2029 vamsasImport.setVisible(false); // Document import to existing session is
2030 // not possible for vamsas-client-1.0.
2033 protected void setupVamsasDisconnectedGui()
2035 vamsasSave.setVisible(false);
2036 vamsasStop.setVisible(false);
2037 vamsasImport.setVisible(true);
2038 vamsasStart.setText(MessageManager
2039 .getString("label.new_vamsas_session"));
2042 public void vamsasStop_actionPerformed(ActionEvent e)
2044 if (v_client != null)
2046 v_client.end_session();
2048 setupVamsasDisconnectedGui();
2052 protected void buildVamsasStMenu()
2054 if (v_client == null)
2056 String[] sess = null;
2059 sess = VamsasApplication.getSessionList();
2060 } catch (Exception e)
2063 "Problem getting current sessions list.", e);
2068 Cache.log.debug("Got current sessions list: "
2069 + sess.length + " entries.");
2070 VamsasStMenu.removeAll();
2071 for (int i = 0; i < sess.length; i++)
2073 JMenuItem sessit = new JMenuItem();
2074 sessit.setText(sess[i]);
2075 sessit.setToolTipText(MessageManager.formatMessage(
2076 "label.connect_to_session", new Object[]
2078 final Desktop dsktp = this;
2079 final String mysesid = sess[i];
2080 sessit.addActionListener(new ActionListener()
2083 public void actionPerformed(ActionEvent e)
2085 if (dsktp.v_client == null)
2087 Thread rthr = new Thread(new Runnable()
2092 dsktp.v_client = new VamsasApplication(dsktp, mysesid);
2093 dsktp.setupVamsasConnectedGui();
2094 dsktp.v_client.initial_update();
2102 VamsasStMenu.add(sessit);
2104 // don't show an empty menu.
2105 VamsasStMenu.setVisible(sess.length > 0);
2110 Cache.log.debug("No current vamsas sessions.");
2111 VamsasStMenu.removeAll();
2112 VamsasStMenu.setVisible(false);
2117 // Not interested in the content. Just hide ourselves.
2118 VamsasStMenu.setVisible(false);
2122 public void vamsasSave_actionPerformed(ActionEvent e)
2124 if (v_client != null)
2126 JalviewFileChooser chooser = new JalviewFileChooser(
2127 Cache.getProperty("LAST_DIRECTORY"), new String[]
2128 { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
2130 { "Vamsas Document" }, "Vamsas Document");
2132 chooser.setFileView(new JalviewFileView());
2133 chooser.setDialogTitle(MessageManager
2134 .getString("label.save_vamsas_document_archive"));
2136 int value = chooser.showSaveDialog(this);
2138 if (value == JalviewFileChooser.APPROVE_OPTION)
2140 java.io.File choice = chooser.getSelectedFile();
2141 JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
2142 "label.saving_vamsas_doc", new Object[]
2143 { choice.getName() }));
2144 Cache.setProperty("LAST_DIRECTORY", choice.getParent());
2145 String warnmsg = null;
2146 String warnttl = null;
2149 v_client.vclient.storeDocument(choice);
2152 warnttl = "Serious Problem saving Vamsas Document";
2153 warnmsg = ex.toString();
2154 Cache.log.error("Error Whilst saving document to "
2157 } catch (Exception ex)
2159 warnttl = "Problem saving Vamsas Document.";
2160 warnmsg = ex.toString();
2161 Cache.log.warn("Exception Whilst saving document to "
2165 removeProgressPanel(progpanel);
2166 if (warnmsg != null)
2168 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2170 warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
2176 JPanel vamUpdate = null;
2179 * hide vamsas user gui bits when a vamsas document event is being handled.
2182 * true to hide gui, false to reveal gui
2184 public void setVamsasUpdate(boolean b)
2186 Cache.log.debug("Setting gui for Vamsas update "
2187 + (b ? "in progress" : "finished"));
2189 if (vamUpdate != null)
2191 this.removeProgressPanel(vamUpdate);
2195 vamUpdate = this.addProgressPanel(MessageManager
2196 .getString("label.updating_vamsas_session"));
2198 vamsasStart.setVisible(!b);
2199 vamsasStop.setVisible(!b);
2200 vamsasSave.setVisible(!b);
2203 public JInternalFrame[] getAllFrames()
2205 return desktop.getAllFrames();
2209 * Checks the given url to see if it gives a response indicating that the user
2210 * should be informed of a new questionnaire.
2214 public void checkForQuestionnaire(String url)
2216 UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
2217 // javax.swing.SwingUtilities.invokeLater(jvq);
2218 new Thread(jvq).start();
2222 * Proxy class for JDesktopPane which optionally displays the current memory
2223 * usage and highlights the desktop area with a red bar if free memory runs
2228 public class MyDesktopPane extends JDesktopPane implements Runnable
2231 private static final float ONE_MB = 1048576f;
2233 boolean showMemoryUsage = false;
2237 java.text.NumberFormat df;
2239 float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
2242 public MyDesktopPane(boolean showMemoryUsage)
2244 showMemoryUsage(showMemoryUsage);
2247 public void showMemoryUsage(boolean showMemoryUsage)
2249 this.showMemoryUsage = showMemoryUsage;
2250 if (showMemoryUsage)
2252 Thread worker = new Thread(this);
2257 public boolean isShowMemoryUsage()
2259 return showMemoryUsage;
2264 df = java.text.NumberFormat.getNumberInstance();
2265 df.setMaximumFractionDigits(2);
2266 runtime = Runtime.getRuntime();
2268 while (showMemoryUsage)
2272 maxMemory = runtime.maxMemory() / ONE_MB;
2273 allocatedMemory = runtime.totalMemory() / ONE_MB;
2274 freeMemory = runtime.freeMemory() / ONE_MB;
2275 totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
2277 percentUsage = (totalFreeMemory / maxMemory) * 100;
2279 // if (percentUsage < 20)
2281 // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
2283 // instance.set.setBorder(border1);
2286 // sleep after showing usage
2288 } catch (Exception ex)
2290 ex.printStackTrace();
2295 public void paintComponent(Graphics g)
2297 if (showMemoryUsage && g != null && df != null)
2299 if (percentUsage < 20)
2301 g.setColor(Color.red);
2303 FontMetrics fm = g.getFontMetrics();
2306 g.drawString(MessageManager.formatMessage(
2307 "label.memory_stats",
2309 { df.format(totalFreeMemory), df.format(maxMemory),
2310 df.format(percentUsage) }), 10,
2311 getHeight() - fm.getHeight());
2318 * fixes stacking order after a modal dialog to ensure windows that should be
2319 * on top actually are
2321 public void relayerWindows()
2326 protected JMenuItem groovyShell;
2328 public void doGroovyCheck()
2330 if (Cache.groovyJarsPresent())
2332 groovyShell = new JMenuItem();
2333 groovyShell.setText(MessageManager.getString("label.groovy_console"));
2334 groovyShell.addActionListener(new ActionListener()
2336 public void actionPerformed(ActionEvent e)
2338 groovyShell_actionPerformed(e);
2341 toolsMenu.add(groovyShell);
2342 groovyShell.setVisible(true);
2347 * Accessor method to quickly get all the AlignmentFrames loaded.
2349 * @return an array of AlignFrame, or null if none found
2351 public static AlignFrame[] getAlignFrames()
2353 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2359 List<AlignFrame> avp = new ArrayList<AlignFrame>();
2361 for (int i = frames.length - 1; i > -1; i--)
2363 if (frames[i] instanceof AlignFrame)
2365 avp.add((AlignFrame) frames[i]);
2367 else if (frames[i] instanceof SplitFrame)
2370 * Also check for a split frame containing an AlignFrame
2372 GSplitFrame sf = (GSplitFrame) frames[i];
2373 if (sf.getTopFrame() instanceof AlignFrame)
2375 avp.add((AlignFrame) sf.getTopFrame());
2377 if (sf.getBottomFrame() instanceof AlignFrame)
2379 avp.add((AlignFrame) sf.getBottomFrame());
2383 if (avp.size() == 0)
2387 AlignFrame afs[] = avp.toArray(new AlignFrame[avp.size()]);
2392 * Returns an array of any AppJmol frames in the Desktop (or null if none).
2396 public GStructureViewer[] getJmols()
2398 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2404 List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
2406 for (int i = frames.length - 1; i > -1; i--)
2408 if (frames[i] instanceof AppJmol)
2410 GStructureViewer af = (GStructureViewer) frames[i];
2414 if (avp.size() == 0)
2418 GStructureViewer afs[] = avp.toArray(new GStructureViewer[avp.size()]);
2423 * Add Groovy Support to Jalview
2425 public void groovyShell_actionPerformed(ActionEvent e)
2427 // use reflection to avoid creating compilation dependency.
2428 if (!Cache.groovyJarsPresent())
2432 .getString("error.implementation_error_cannot_create_groovyshell"));
2436 Class<?> gcClass = Desktop.class.getClassLoader().loadClass(
2437 "groovy.ui.Console");
2438 Constructor<?> gccons = gcClass.getConstructor();
2439 java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
2441 { String.class, Object.class });
2442 java.lang.reflect.Method run = gcClass.getMethod("run");
2443 Object gc = gccons.newInstance();
2444 setvar.invoke(gc, new Object[]
2445 { "Jalview", this });
2447 } catch (Exception ex)
2449 Cache.log.error("Groovy Shell Creation failed.", ex);
2450 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2452 MessageManager.getString("label.couldnt_create_groovy_shell"),
2453 MessageManager.getString("label.groovy_support_failed"),
2454 JOptionPane.ERROR_MESSAGE);
2459 * Progress bars managed by the IProgressIndicator method.
2461 private Hashtable<Long, JPanel> progressBars;
2463 private Hashtable<Long, IProgressIndicatorHandler> progressBarHandlers;
2468 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
2470 public void setProgressBar(String message, long id)
2472 if (progressBars == null)
2474 progressBars = new Hashtable<Long, JPanel>();
2475 progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
2478 if (progressBars.get(new Long(id)) != null)
2480 JPanel progressPanel = progressBars.remove(new Long(id));
2481 if (progressBarHandlers.contains(new Long(id)))
2483 progressBarHandlers.remove(new Long(id));
2485 removeProgressPanel(progressPanel);
2489 progressBars.put(new Long(id), addProgressPanel(message));
2496 * @see jalview.gui.IProgressIndicator#registerHandler(long,
2497 * jalview.gui.IProgressIndicatorHandler)
2499 public void registerHandler(final long id,
2500 final IProgressIndicatorHandler handler)
2502 if (progressBarHandlers == null
2503 || !progressBars.containsKey(new Long(id)))
2507 .getString("error.call_setprogressbar_before_registering_handler"));
2509 progressBarHandlers.put(new Long(id), handler);
2510 final JPanel progressPanel = progressBars.get(new Long(id));
2511 if (handler.canCancel())
2513 JButton cancel = new JButton(
2514 MessageManager.getString("action.cancel"));
2515 final IProgressIndicator us = this;
2516 cancel.addActionListener(new ActionListener()
2519 public void actionPerformed(ActionEvent e)
2521 handler.cancelActivity(id);
2522 us.setProgressBar(MessageManager.formatMessage(
2523 "label.cancelled_params", new Object[]
2524 { ((JLabel) progressPanel.getComponent(0)).getText() }),
2528 progressPanel.add(cancel, BorderLayout.EAST);
2534 * @return true if any progress bars are still active
2537 public boolean operationInProgress()
2539 if (progressBars != null && progressBars.size() > 0)
2547 * This will return the first AlignFrame holding the given viewport instance. It
2548 * will break if there are more than one AlignFrames viewing a particular av.
2551 * @return alignFrame for viewport
2553 public static AlignFrame getAlignFrameFor(AlignViewportI viewport)
2555 if (desktop != null)
2557 AlignmentPanel[] aps = getAlignmentPanels(viewport
2558 .getSequenceSetId());
2559 for (int panel = 0; aps != null && panel < aps.length; panel++)
2561 if (aps[panel] != null && aps[panel].av == viewport)
2563 return aps[panel].alignFrame;
2570 public VamsasApplication getVamsasApplication()
2577 * flag set if jalview GUI is being operated programmatically
2579 private boolean inBatchMode = false;
2582 * check if jalview GUI is being operated programmatically
2584 * @return inBatchMode
2586 public boolean isInBatchMode()
2592 * set flag if jalview GUI is being operated programmatically
2594 * @param inBatchMode
2596 public void setInBatchMode(boolean inBatchMode)
2598 this.inBatchMode = inBatchMode;
2601 public void startServiceDiscovery()
2603 startServiceDiscovery(false);
2606 public void startServiceDiscovery(boolean blocking)
2608 boolean alive = true;
2609 Thread t0 = null, t1 = null, t2 = null;
2610 // JAL-940 - JALVIEW 1 services are now being EOLed as of JABA 2.1 release
2613 // todo: changesupport handlers need to be transferred
2614 if (discoverer == null)
2616 discoverer = new jalview.ws.jws1.Discoverer();
2617 // register PCS handler for desktop.
2618 discoverer.addPropertyChangeListener(changeSupport);
2620 // JAL-940 - disabled JWS1 service configuration - always start discoverer
2621 // until we phase out completely
2622 (t0 = new Thread(discoverer)).start();
2625 if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
2627 if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
2629 jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
2631 t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
2637 // TODO: do rest service discovery
2646 } catch (Exception e)
2649 alive = (t1 != null && t1.isAlive())
2650 || (t2 != null && t2.isAlive())
2651 || (t3 != null && t3.isAlive())
2652 || (t0 != null && t0.isAlive());
2658 * called to check if the service discovery process completed successfully.
2662 protected void JalviewServicesChanged(PropertyChangeEvent evt)
2664 if (evt.getNewValue() == null || evt.getNewValue() instanceof Vector)
2666 final String ermsg = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
2667 .getErrorMessages();
2670 if (Cache.getDefault("SHOW_WSDISCOVERY_ERRORS", true))
2672 if (serviceChangedDialog == null)
2674 // only run if we aren't already displaying one of these.
2675 addDialogThread(serviceChangedDialog = new Runnable()
2681 * JalviewDialog jd =new JalviewDialog() {
2683 * @Override protected void cancelPressed() { // TODO
2684 * Auto-generated method stub
2686 * }@Override protected void okPressed() { // TODO
2687 * Auto-generated method stub
2689 * }@Override protected void raiseClosed() { // TODO
2690 * Auto-generated method stub
2692 * } }; jd.initDialogFrame(new
2693 * JLabel("<html><table width=\"450\"><tr><td>" + ermsg +
2694 * "<br/>It may be that you have invalid JABA URLs in your web service preferences,"
2695 * + " or mis-configured HTTP proxy settings.<br/>" +
2696 * "Check the <em>Connections</em> and <em>Web services</em> tab of the"
2698 * " Tools->Preferences dialog box to change them.</td></tr></table></html>"
2699 * ), true, true, "Web Service Configuration Problem", 450,
2702 * jd.waitForInput();
2708 "<html><table width=\"450\"><tr><td>"
2710 + "</td></tr></table>"
2711 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
2712 + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
2713 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
2714 + " Tools->Preferences dialog box to change them.</p></html>"),
2715 "Web Service Configuration Problem",
2716 JOptionPane.DEFAULT_OPTION,
2717 JOptionPane.ERROR_MESSAGE);
2718 serviceChangedDialog = null;
2727 .error("Errors reported by JABA discovery service. Check web services preferences.\n"
2734 private Runnable serviceChangedDialog = null;
2737 * start a thread to open a URL in the configured browser. Pops up a warning
2738 * dialog to the user if there is an exception when calling out to the browser
2743 public static void showUrl(final String url)
2745 showUrl(url, Desktop.instance);
2749 * Like showUrl but allows progress handler to be specified
2753 * (null) or object implementing IProgressIndicator
2755 public static void showUrl(final String url,
2756 final IProgressIndicator progress)
2758 new Thread(new Runnable()
2764 if (progress != null)
2766 progress.setProgressBar(MessageManager.formatMessage(
2767 "status.opening_params", new Object[]
2768 { url }), this.hashCode());
2770 BrowserLauncher.openURL(url);
2771 } catch (Exception ex)
2773 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2775 .getString("label.web_browser_not_found_unix"),
2776 MessageManager.getString("label.web_browser_not_found"),
2777 JOptionPane.WARNING_MESSAGE);
2779 ex.printStackTrace();
2781 if (progress != null)
2783 progress.setProgressBar(null, this.hashCode());
2789 public static WsParamSetManager wsparamManager = null;
2791 public static ParamManager getUserParameterStore()
2793 if (wsparamManager == null)
2795 wsparamManager = new WsParamSetManager();
2797 return wsparamManager;
2801 * static hyperlink handler proxy method for use by Jalview's internal windows
2805 public static void hyperlinkUpdate(HyperlinkEvent e)
2807 if (e.getEventType() == EventType.ACTIVATED)
2812 url = e.getURL().toString();
2813 Desktop.showUrl(url);
2814 } catch (Exception x)
2818 if (Cache.log != null)
2820 Cache.log.error("Couldn't handle string " + url + " as a URL.");
2824 System.err.println("Couldn't handle string " + url
2828 // ignore any exceptions due to dud links.
2835 * single thread that handles display of dialogs to user.
2837 ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
2840 * flag indicating if dialogExecutor should try to acquire a permit
2842 private volatile boolean dialogPause = true;
2847 private java.util.concurrent.Semaphore block = new Semaphore(0);
2850 * add another dialog thread to the queue
2854 public void addDialogThread(final Runnable prompter)
2856 dialogExecutor.submit(new Runnable()
2865 } catch (InterruptedException x)
2870 if (instance == null)
2876 SwingUtilities.invokeAndWait(prompter);
2877 } catch (Exception q)
2879 Cache.log.warn("Unexpected Exception in dialog thread.", q);
2885 public void startDialogQueue()
2887 // set the flag so we don't pause waiting for another permit and semaphore
2888 // the current task to begin
2889 dialogPause = false;
2894 protected void snapShotWindow_actionPerformed(ActionEvent e)
2898 ImageMaker im = new ImageMaker(this, ImageMaker.TYPE.EPS,
2899 "View of Desktop", getWidth(), getHeight(), of = new File(
2900 "Jalview_snapshot" + System.currentTimeMillis()
2901 + ".eps"), "View of desktop");
2904 paintAll(im.getGraphics());
2906 } catch (Exception q)
2908 Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(),
2912 Cache.log.info("Successfully written snapshot to file "
2913 + of.getAbsolutePath());
2917 * Explode the views in the given frame into separate AlignFrame windows.
2921 public void explodeViews(SplitFrame sf)
2923 AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame();
2924 AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame();
2925 List<? extends AlignmentViewPanel> topPanels = oldTopFrame
2927 List<? extends AlignmentViewPanel> bottomPanels = oldBottomFrame
2929 int viewCount = topPanels.size();
2936 * Processing in reverse order works, forwards order leaves the first panels
2937 * not visible. I don't know why!
2939 for (int i = viewCount - 1; i >= 0; i--)
2942 * Make new top and bottom frames. These take over the respective
2943 * AlignmentPanel objects, including their AlignmentViewports, so the
2944 * cdna/protein relationships between the viewports is carried over to the
2947 AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
2948 AlignFrame newTopFrame = new AlignFrame(topPanel);
2949 newTopFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
2950 AlignFrame.DEFAULT_HEIGHT));
2951 newTopFrame.setVisible(true);
2952 AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
2953 AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
2954 newBottomFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
2955 AlignFrame.DEFAULT_HEIGHT));
2956 newBottomFrame.setVisible(true);
2957 topPanel.av.setGatherViewsHere(false);
2958 bottomPanel.av.setGatherViewsHere(false);
2959 JInternalFrame splitFrame = new SplitFrame(newTopFrame,
2961 // either panel may hold previous exploded frame geometry
2962 Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
2963 .getExplodedGeometry();
2964 if (geometry != null)
2966 splitFrame.setBounds(geometry);
2968 Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
2972 * Clear references to the panels (now relocated in the new SplitFrames)
2973 * before closing the old SplitFrame.
2976 bottomPanels.clear();
2981 * Gather expanded split frames, sharing the same pairs of sequence set ids,
2982 * back into the given SplitFrame as additional views. Note that the gathered
2983 * frames may themselves have multiple views.
2987 public void gatherViews(GSplitFrame source)
2989 AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
2990 AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
2991 myTopFrame.viewport.setExplodedGeometry(source.getBounds());
2992 myBottomFrame.viewport.setExplodedGeometry(source.getBounds());
2993 myTopFrame.viewport.setGatherViewsHere(true);
2994 myBottomFrame.viewport.setGatherViewsHere(true);
2995 String topViewId = myTopFrame.viewport.getSequenceSetId();
2996 String bottomViewId = myBottomFrame.viewport.getSequenceSetId();
2998 JInternalFrame[] frames = desktop.getAllFrames();
2999 for (JInternalFrame frame : frames)
3001 if (frame instanceof SplitFrame && frame != source)
3003 SplitFrame sf = (SplitFrame) frame;
3004 AlignFrame topFrame = (AlignFrame) sf.getTopFrame();
3005 AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame();
3006 boolean gatherThis = false;
3007 for (int a = 0; a < topFrame.alignPanels.size(); a++)
3009 AlignmentPanel topPanel = topFrame.alignPanels.get(a);
3010 AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a);
3011 if (topViewId.equals(topPanel.av.getSequenceSetId())
3012 && bottomViewId.equals(bottomPanel.av.getSequenceSetId()))
3015 topPanel.av.setGatherViewsHere(false);
3016 bottomPanel.av.setGatherViewsHere(false);
3017 // both panels refer to the same split frame geometry
3018 Rectangle position = sf.getBounds();
3019 topPanel.av.setExplodedGeometry(position);
3020 bottomPanel.av.setExplodedGeometry(position);
3021 myTopFrame.addAlignmentPanel(topPanel, false);
3022 myBottomFrame.addAlignmentPanel(bottomPanel, false);
3028 topFrame.getAlignPanels().clear();
3029 bottomFrame.getAlignPanels().clear();
3036 * The dust settles...give focus to the tab we did this from.
3038 myTopFrame.setDisplayedView(myTopFrame.alignPanel);
3042 // public static AlignFrame getCurrentAlignFrame()
3044 // return currentAlignFrame;
3047 // public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
3049 // Desktop.currentAlignFrame = currentAlignFrame;