X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FDesktop.java;h=717fb1a37235cf4532e5c83bd9332ef1a1465987;hb=6200addf078b7f7ace90597dc056dafc7fc602c1;hp=e13a63e1a4f6791e1e692f77dd00f52016ca6628;hpb=4b1c969e87feaefd4fb9c49ba3d6b828b3ce1a9c;p=jalview.git diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index e13a63e..717fb1a 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -39,7 +39,6 @@ import jalview.io.FormatAdapter; import jalview.io.IdentifyFile; import jalview.io.JalviewFileChooser; import jalview.io.JalviewFileView; -import jalview.jbgui.GDesktop; import jalview.jbgui.GSplitFrame; import jalview.jbgui.GStructureViewer; import jalview.project.Jalview2XML; @@ -49,9 +48,9 @@ import jalview.util.BrowserLauncher; import jalview.util.ImageMaker.TYPE; import jalview.util.MessageManager; import jalview.util.Platform; +import jalview.util.ShortcutKeyMaskExWrapper; import jalview.util.UrlConstants; import jalview.viewmodel.AlignmentViewport; -import jalview.ws.jws1.Discoverer; import jalview.ws.params.ParamManager; import jalview.ws.utils.UrlDownloadClient; @@ -84,12 +83,13 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; +import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.ListIterator; @@ -111,7 +111,6 @@ import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDesktopPane; -import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JMenuItem; @@ -125,8 +124,6 @@ import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent.EventType; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; import org.stackoverflowusers.file.WindowsShortcut; @@ -137,11 +134,18 @@ import org.stackoverflowusers.file.WindowsShortcut; * @author $author$ * @version $Revision: 1.155 $ */ -@SuppressWarnings("serial") -public class Desktop extends GDesktop +public class Desktop extends jalview.jbgui.GDesktop implements DropTargetListener, ClipboardOwner, IProgressIndicator, StructureSelectionManagerProvider, ApplicationSingletonI { + private static final String CITATION = "

Development managed by The Barton Group, University of Dundee, Scotland, UK.
" + + "

For help, see the FAQ at www.jalview.org/faq and/or join the jalview-discuss@jalview.org mailing list" + + "

If you use Jalview, please cite:" + + "
Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)" + + "
Jalview Version 2 - a multiple sequence alignment editor and analysis workbench" + + "
Bioinformatics doi: 10.1093/bioinformatics/btp033"; + + private static final String DEFAULT_AUTHORS = "The Jalview Authors (See AUTHORS file for current list)"; private final static int DEFAULT_MIN_WIDTH = 300; @@ -153,12 +157,16 @@ public class Desktop extends GDesktop private final static String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES"; + protected static final String CONFIRM_KEYBOARD_QUIT = "CONFIRM_KEYBOARD_QUIT"; + + public static HashMap savingFiles = new HashMap<>(); + private JalviewChangeSupport changeSupport = new JalviewChangeSupport(); /** * news reader - null if it was never started. */ - BlogReader jvnews = null; + private BlogReader jvnews = null; private File projectFile; @@ -197,12 +205,6 @@ public class Desktop extends GDesktop listener); } - public static MyDesktopPane getDesktopPane() - { - Desktop desktop = Desktop.getInstance(); - return desktop == null ? null : desktop.desktopPane; - } - public static StructureSelectionManager getStructureSelectionManager() { return StructureSelectionManager @@ -215,10 +217,13 @@ public class Desktop extends GDesktop static final int yOffset = 30; - public Discoverer discoverer; + // BH was static + public jalview.ws.jws1.Discoverer discoverer; + //BH was static public Object[] jalviewClipboard; +//BH was static public boolean internalCopy = false; private static int fileLoadingCount = 0; @@ -349,23 +354,6 @@ public class Desktop extends GDesktop // All other methods, simply delegate } - - public MyDesktopPane desktopPane; - - /** - * Answers an 'application scope' singleton instance of this class. Separate - * SwingJS 'applets' running in the same browser page will each have a - * distinct instance of Desktop. - * - * @return - */ - public static Desktop getInstance() - { - return Jalview.isHeadlessMode() ? null - : (Desktop) ApplicationSingletonProvider - .getInstance(Desktop.class); - } - /** * Private constructor enforces singleton pattern. It is called by reflection * from ApplicationSingletonProvider.getInstance(). @@ -380,22 +368,49 @@ public class Desktop extends GDesktop * block are spawned off as threads rather than waited for during this * constructor. */ - if (!Platform.isJS()) + + doConfigureStructurePrefs(); + setTitle("Jalview " + Cache.getProperty("VERSION")); + + try + { + if (Platform.getJavaVersion() >= 11) + { + // BH use reflection so that this code can be in both the Java8 and + // Java11 versions + Class j11APQHandlers = Class + .forName("jalview.gui.APQHandlers"); + Method meth = j11APQHandlers.getMethod("setAPQHandlers", + new Class[] + { Desktop.class }); + meth.invoke(j11APQHandlers.newInstance(), this); + } + } catch (Throwable t) { - doVamsasClientCheck(); + System.out.println( + "Desktop Error setting APQHandlers: " + t.toString()); } - doConfigureStructurePrefs(); - setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION")); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE", + addWindowListener(new WindowAdapter() + { + + @Override + public void windowClosing(WindowEvent ev) + { + quit(); + } + }); + + boolean selmemusage = Cache.getDefault("SHOW_MEMUSAGE", false); - boolean showjconsole = jalview.bin.Cache - .getDefault("SHOW_JAVA_CONSOLE", false); - desktopPane = new MyDesktopPane(selmemusage); - showMemusage.setSelected(selmemusage); - desktopPane.setBackground(Color.white); + boolean showjconsole = Cache.getDefault("SHOW_JAVA_CONSOLE", + false); + desktopPane = new MyDesktopPane(selmemusage); + + showMemusage.setSelected(selmemusage); + desktopPane.setBackground(Color.white); + getContentPane().setLayout(new BorderLayout()); // alternate config - have scrollbars - see notes in JAL-153 // JScrollPane sp = new JScrollPane(); @@ -450,19 +465,7 @@ public class Desktop extends GDesktop { jconsole = new Console(this, showjconsole); - // add essential build information - jconsole.setHeader("Jalview Version: " - + jalview.bin.Cache.getProperty("VERSION") + "\n" - + "Jalview Installation: " - + jalview.bin.Cache.getDefault("INSTALLATION", "unknown") - + "\n" + "Build Date: " - + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") - + "\n" + "Java version: " - + System.getProperty("java.version") + "\n" - + System.getProperty("os.arch") + " " - + System.getProperty("os.name") + " " - + System.getProperty("os.version")); - + jconsole.setHeader(Cache.getVersionDetailsForConsole()); showConsole(showjconsole); showNews.setVisible(false); @@ -480,7 +483,7 @@ public class Desktop extends GDesktop @Override public void run() { - new SplashScreen(); + new SplashScreen(true); } }); @@ -576,14 +579,14 @@ public class Desktop extends GDesktop // configure services StructureSelectionManager ssm = StructureSelectionManager .getStructureSelectionManager(this); - if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true)) + if (Cache.getDefault(Preferences.ADD_SS_ANN, true)) { - ssm.setAddTempFacAnnot(jalview.bin.Cache + ssm.setAddTempFacAnnot(Cache .getDefault(Preferences.ADD_TEMPFACT_ANN, true)); - ssm.setProcessSecondaryStructure(jalview.bin.Cache + ssm.setProcessSecondaryStructure(Cache .getDefault(Preferences.STRUCT_FROM_PDB, true)); ssm.setSecStructServices( - jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true)); + Cache.getDefault(Preferences.USE_RNAVIEW, true)); } else { @@ -619,7 +622,6 @@ public class Desktop extends GDesktop public void run() { Cache.log.debug("Downloading data from identifiers.org"); - // UrlDownloadClient client = new UrlDownloadClient(); try { UrlDownloadClient.download(IdOrgSettings.getUrl(), @@ -674,25 +676,25 @@ public class Desktop extends GDesktop { // TODO: lock aspect ratio for scaling desktop Bug #0058199 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X"); - String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y"); - String width = jalview.bin.Cache + String x = Cache.getProperty(windowName + "SCREEN_X"); + String y = Cache.getProperty(windowName + "SCREEN_Y"); + String width = Cache .getProperty(windowName + "SCREEN_WIDTH"); - String height = jalview.bin.Cache + String height = Cache .getProperty(windowName + "SCREEN_HEIGHT"); if ((x != null) && (y != null) && (width != null) && (height != null)) { int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer.parseInt(width), ih = Integer.parseInt(height); - if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null) + if (Cache.getProperty("SCREENGEOMETRY_WIDTH") != null) { // attempt #1 - try to cope with change in screen geometry - this // version doesn't preserve original jv aspect ratio. // take ratio of current screen size vs original screen size. double sw = ((1f * screenSize.width) / (1f * Integer.parseInt( - jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH")))); + Cache.getProperty("SCREENGEOMETRY_WIDTH")))); double sh = ((1f * screenSize.height) / (1f * Integer.parseInt( - jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT")))); + Cache.getProperty("SCREENGEOMETRY_HEIGHT")))); // rescale the bounds depending upon the current screen geometry. ix = (int) (ix * sw); iw = (int) (iw * sw); @@ -700,17 +702,17 @@ public class Desktop extends GDesktop ih = (int) (ih * sh); while (ix >= screenSize.width) { - jalview.bin.Cache.log.debug( + Cache.log.debug( "Window geometry location recall error: shifting horizontal to within screenbounds."); ix -= screenSize.width; } while (iy >= screenSize.height) { - jalview.bin.Cache.log.debug( + Cache.log.debug( "Window geometry location recall error: shifting vertical to within screenbounds."); iy -= screenSize.height; } - jalview.bin.Cache.log.debug( + Cache.log.debug( "Got last known dimensions for " + windowName + ": x:" + ix + " y:" + iy + " width:" + iw + " height:" + ih); } @@ -720,46 +722,6 @@ public class Desktop extends GDesktop return null; } - private void doVamsasClientCheck() - { - if (Cache.vamsasJarsPresent()) - { - setupVamsasDisconnectedGui(); - VamsasMenu.setVisible(true); - final Desktop us = this; - VamsasMenu.addMenuListener(new MenuListener() - { - // this listener remembers when the menu was first selected, and - // doesn't rebuild the session list until it has been cleared and - // reselected again. - boolean refresh = true; - - @Override - public void menuCanceled(MenuEvent e) - { - refresh = true; - } - - @Override - public void menuDeselected(MenuEvent e) - { - refresh = true; - } - - @Override - public void menuSelected(MenuEvent e) - { - if (refresh) - { - us.buildVamsasStMenu(); - refresh = false; - } - } - }); - vamsasStart.setVisible(true); - } - } - protected void showPasteMenu(int x, int y) { JPopupMenu popup = new JPopupMenu(); @@ -793,7 +755,7 @@ public class Desktop extends GDesktop FileFormatI format = new IdentifyFile().identify(file, DataSourceType.PASTE); - new FileLoader().loadFile(file, DataSourceType.PASTE, format); + new FileLoader().LoadFile(file, DataSourceType.PASTE, format); } } catch (Exception ex) @@ -895,6 +857,7 @@ public class Desktop extends GDesktop // the current window title frame.setTitle(title); + // BH fix if (w > 0 && (frame.getWidth() < 1 || frame.getHeight() < 1)) { frame.setSize(w, h); @@ -1031,6 +994,7 @@ public class Desktop extends GDesktop */ private static void setKeyBindings(JInternalFrame frame) { + @SuppressWarnings("serial") final Action closeAction = new AbstractAction() { @Override @@ -1046,7 +1010,7 @@ public class Desktop extends GDesktop KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK); KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); + ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx()); InputMap inputMap = frame .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); @@ -1141,9 +1105,13 @@ public class Desktop extends GDesktop if (file instanceof File) { Platform.cacheFileData((File) file); + new FileLoader().loadFile(null, (File) file, protocol, format); } - new FileLoader().loadFile(null, file, protocol, format); + else + { + new FileLoader().LoadFile((String) file, protocol, format); + } } } catch (Exception ex) { @@ -1165,7 +1133,7 @@ public class Desktop extends GDesktop { String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT"); JalviewFileChooser chooser = JalviewFileChooser - .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat, true); + .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat, BackupFiles.getEnabled()); chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle( @@ -1199,7 +1167,7 @@ public class Desktop extends GDesktop } } - new FileLoader().loadFile(viewport, selectedFile, + new FileLoader().LoadFile(viewport, selectedFile, DataSourceType.FILE, format); } }); @@ -1273,12 +1241,12 @@ public class Desktop extends GDesktop { if (viewport != null) { - new FileLoader().loadFile(viewport, url, DataSourceType.URL, + new FileLoader().LoadFile(viewport, url, DataSourceType.URL, FileFormat.Jalview); } else { - new FileLoader().loadFile(url, DataSourceType.URL, + new FileLoader().LoadFile(url, DataSourceType.URL, FileFormat.Jalview); } } @@ -1308,12 +1276,12 @@ public class Desktop extends GDesktop if (viewport != null) { - new FileLoader().loadFile(viewport, url, DataSourceType.URL, + new FileLoader().LoadFile(viewport, url, DataSourceType.URL, format); } else { - new FileLoader().loadFile(url, DataSourceType.URL, format); + new FileLoader().LoadFile(url, DataSourceType.URL, format); } } } @@ -1353,9 +1321,9 @@ public class Desktop extends GDesktop public void quit() { Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); - jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH", + Cache.setProperty("SCREENGEOMETRY_WIDTH", screen.width + ""); - jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", + Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height + ""); storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y, getWidth(), getHeight())); @@ -1387,14 +1355,14 @@ public class Desktop extends GDesktop private void storeLastKnownDimensions(String string, Rectangle jc) { - jalview.bin.Cache.log.debug("Storing last known dimensions for " + Cache.log.debug("Storing last known dimensions for " + string + ": x:" + jc.x + " y:" + jc.y + " width:" + jc.width + " height:" + jc.height); - jalview.bin.Cache.setProperty(string + "SCREEN_X", jc.x + ""); - jalview.bin.Cache.setProperty(string + "SCREEN_Y", jc.y + ""); - jalview.bin.Cache.setProperty(string + "SCREEN_WIDTH", jc.width + ""); - jalview.bin.Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + ""); + Cache.setProperty(string + "SCREEN_X", jc.x + ""); + Cache.setProperty(string + "SCREEN_Y", jc.y + ""); + Cache.setProperty(string + "SCREEN_WIDTH", jc.width + ""); + Cache.setProperty(string + "SCREEN_HEIGHT", jc.height + ""); } /** @@ -1406,53 +1374,45 @@ public class Desktop extends GDesktop @Override public void aboutMenuItem_actionPerformed(ActionEvent e) { - // StringBuffer message = getAboutMessage(false); - // JvOptionPane.showInternalMessageDialog(Desktop.getDesktop(), - // - // message.toString(), "About Jalview", JvOptionPane.INFORMATION_MESSAGE); new Thread(new Runnable() { @Override public void run() { + // BH! true meaning "interactive" here (applet branch); was false in + // develop version?? new SplashScreen(true); } }).start(); } - public StringBuffer getAboutMessage(boolean shortv) + /** + * Returns the html text for the About screen, including any available version + * number, build details, author details and citation reference, but without + * the enclosing {@code html} tags + * + * @return + */ + public String getAboutMessage() { - StringBuffer message = new StringBuffer(); - message.append(""); - if (shortv) - { - message.append("

Version: " - + jalview.bin.Cache.getProperty("VERSION") - + "

"); - message.append("Last Updated: " - + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") - + ""); + StringBuilder message = new StringBuilder(1024); + message.append("

Version: ") + .append(Cache.getProperty("VERSION")).append("

") + .append("Built: ") + .append(Cache.getDefault("BUILD_DATE", "unknown")) + .append(" from ").append(Cache.getBuildDetailsForSplash()) + .append(""); - } - else + String latestVersion = Cache.getDefault("LATEST_VERSION", "Checking"); + if (latestVersion.equals("Checking")) { - - message.append("Version " - + jalview.bin.Cache.getProperty("VERSION") - + "; last updated: " - + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")); + // JBP removed this message for 2.11: May be reinstated in future version + // message.append("
...Checking latest version...
"); } - - if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking") - .equals("Checking")) - { - message.append("
...Checking latest version...
"); - } - else if (!jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking") - .equals(jalview.bin.Cache.getProperty("VERSION"))) + else if (!latestVersion.equals(Cache.getProperty("VERSION"))) { boolean red = false; - if (jalview.bin.Cache.getProperty("VERSION").toLowerCase() + if (Cache.getProperty("VERSION").toLowerCase() .indexOf("automated build") == -1) { red = true; @@ -1461,29 +1421,22 @@ public class Desktop extends GDesktop message.append("
"); } - message.append("
!! Version " - + jalview.bin.Cache.getDefault("LATEST_VERSION", - "..Checking..") - + " is available for download from " - + jalview.bin.Cache.getDefault("www.jalview.org", - "http://www.jalview.org") - + " !!"); + message.append("
!! Version ") + .append(Cache.getDefault("LATEST_VERSION", "..Checking..")) + .append(" is available for download from ") + .append(Cache.getDefault("www.jalview.org", + "http://www.jalview.org")) + .append(" !!"); if (red) { message.append("
"); } } - message.append("
Authors: " + jalview.bin.Cache.getDefault( - "AUTHORFNAMES", - "The Jalview Authors (See AUTHORS file for current list)") - + "

Development managed by The Barton Group, University of Dundee, Scotland, UK.
" - + "

For help, see the FAQ at www.jalview.org/faq and/or join the jalview-discuss@jalview.org mailing list" - + "

If you use Jalview, please cite:" - + "
Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)" - + "
Jalview Version 2 - a multiple sequence alignment editor and analysis workbench" - + "
Bioinformatics doi: 10.1093/bioinformatics/btp033" - + ""); - return message; + message.append("
Authors: "); + message.append(Cache.getDefault("AUTHORFNAMES", DEFAULT_AUTHORS)); + message.append(CITATION); + + return message.toString(); } /** @@ -1533,10 +1486,6 @@ public class Desktop extends GDesktop } Jalview.setCurrentAlignFrame(null); System.out.println("ALL CLOSED"); - if (v_client != null) - { - // TODO clear binding to vamsas document objects on close_all - } /* * reset state of singleton objects as appropriate (clear down session state @@ -1572,9 +1521,9 @@ public class Desktop extends GDesktop protected void garbageCollect_actionPerformed(ActionEvent e) { // We simply collect the garbage - jalview.bin.Cache.log.debug("Collecting garbage..."); + Cache.log.debug("Collecting garbage..."); System.gc(); - jalview.bin.Cache.log.debug("Finished garbage collection."); + Cache.log.debug("Finished garbage collection."); } /* @@ -1764,13 +1713,13 @@ public class Desktop extends GDesktop setProgressBar(MessageManager.formatMessage( "label.saving_jalview_project", new Object[] { chosenFile.getName() }), chosenFile.hashCode()); - jalview.bin.Cache.setProperty("LAST_DIRECTORY", + Cache.setProperty("LAST_DIRECTORY", chosenFile.getParent()); // TODO catch and handle errors for savestate // TODO prevent user from messing with the Desktop whilst we're saving try { - boolean doBackup = BackupFiles.getEnabled(); + boolean doBackup = BackupFiles.getEnabled(); BackupFiles backupfiles = doBackup ? new BackupFiles(chosenFile) : null; new Jalview2XML().saveState(doBackup ? backupfiles.getTempFile() : chosenFile); @@ -1830,7 +1779,7 @@ public class Desktop extends GDesktop "Jalview Project (old)" }; JalviewFileChooser chooser = new JalviewFileChooser( Cache.getProperty("LAST_DIRECTORY"), suffix, desc, - "Jalview Project", true, true); // last two booleans: allFiles, + "Jalview Project", true, BackupFiles.getEnabled()); // last two booleans: allFiles, // allowBackupFiles chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle(MessageManager.getString("label.restore_state")); @@ -1848,24 +1797,26 @@ public class Desktop extends GDesktop @Override public void run() { - try + try { + // BH was String "choice" here but needs to be File object new Jalview2XML().loadJalviewAlign(selectedFile); } catch (OutOfMemoryError oom) - { - new OOMWarning("Whilst loading project from " + choice, oom); - } catch (Exception ex) - { - Cache.log.error( - "Problems whilst loading project from " + choice, ex); + { + new OOMWarning("Whilst loading project from " + choice, oom); + } catch (Exception ex) + { + Cache.log.error( + "Problems whilst loading project from " + choice, ex); JvOptionPane.showMessageDialog(Desktop.getDesktopPane(), - MessageManager.formatMessage( - "label.error_whilst_loading_project_from", - new Object[] - { choice }), - MessageManager.getString("label.couldnt_load_project"), - JvOptionPane.WARNING_MESSAGE); - } + MessageManager.formatMessage( + "label.error_whilst_loading_project_from", + new Object[] + { choice }), + MessageManager + .getString("label.couldnt_load_project"), + JvOptionPane.WARNING_MESSAGE); + } } }).start(); } @@ -2057,11 +2008,29 @@ public class Desktop extends GDesktop return; } + // BH! not in applet branch + // FIXME: ideally should use UI interface API + FeatureSettings viewFeatureSettings = (af.featureSettings != null + && af.featureSettings.isOpen()) + ? af.featureSettings + : null; + Rectangle fsBounds = af.getFeatureSettingsGeometry(); for (int i = 0; i < size; i++) { AlignmentPanel ap = af.alignPanels.get(i); AlignFrame newaf = new AlignFrame(ap); + // BH! not in applet branch + // transfer reference for existing feature settings to new alignFrame + if (ap == af.alignPanel) + { + if (viewFeatureSettings != null && viewFeatureSettings.fr.ap == ap) + { + newaf.featureSettings = viewFeatureSettings; + } + newaf.setFeatureSettingsGeometry(fsBounds); + } + /* * Restore the view's last exploded frame geometry if known. Multiple * views from one exploded frame share and restore the same (frame) @@ -2077,8 +2046,19 @@ public class Desktop extends GDesktop addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); + // BH! not in applet branch + // and materialise a new feature settings dialog instance for the new alignframe + // (closes the old as if 'OK' was pressed) + if (ap == af.alignPanel && newaf.featureSettings != null + && newaf.featureSettings.isOpen() + && af.alignPanel.getAlignViewport().isShowSequenceFeatures()) + { + newaf.showFeatureSettingsUI(); + } } + // BH! not in applet branch + af.featureSettings = null; af.alignPanels.clear(); af.closeMenuItem_actionPerformed(true); @@ -2119,374 +2099,32 @@ public class Desktop extends GDesktop if (gatherThis) { - af.alignPanels.clear(); - af.closeMenuItem_actionPerformed(true); - } - } - } - - } - - jalview.gui.VamsasApplication v_client = null; - - @Override - public void vamsasImport_actionPerformed(ActionEvent e) - { - // TODO: JAL-3048 not needed for Jalview-JS - - if (v_client == null) - { - // Load and try to start a session. - JalviewFileChooser chooser = new JalviewFileChooser( - jalview.bin.Cache.getProperty("LAST_DIRECTORY")); - - chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle( - MessageManager.getString("label.open_saved_vamsas_session")); - chooser.setToolTipText(MessageManager.getString( - "label.select_vamsas_session_opened_as_new_vamsas_session")); - - int value = chooser.showOpenDialog(this); - - if (value == JalviewFileChooser.APPROVE_OPTION) - { - String fle = chooser.getSelectedFile().toString(); - if (!vamsasImport(chooser.getSelectedFile())) - { - JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(), - MessageManager.formatMessage( - "label.couldnt_import_as_vamsas_session", - new Object[] - { fle }), - MessageManager - .getString("label.vamsas_document_import_failed"), - JvOptionPane.ERROR_MESSAGE); - } - } - } - else - { - jalview.bin.Cache.log.error( - "Implementation error - load session from a running session is not supported."); - } - } - - /** - * import file into a new vamsas session (uses jalview.gui.VamsasApplication) - * - * @param file - * @return true if import was a success and a session was started. - */ - public boolean vamsasImport(URL url) - { - // TODO: create progress bar - if (v_client != null) - { - - jalview.bin.Cache.log.error( - "Implementation error - load session from a running session is not supported."); - return false; - } - - try - { - // copy the URL content to a temporary local file - // TODO: be a bit cleverer here with nio (?!) - File file = File.createTempFile("vdocfromurl", ".vdj"); - FileOutputStream fos = new FileOutputStream(file); - BufferedInputStream bis = new BufferedInputStream(url.openStream()); - byte[] buffer = new byte[2048]; - int ln; - while ((ln = bis.read(buffer)) > -1) - { - fos.write(buffer, 0, ln); - } - bis.close(); - fos.close(); - v_client = new jalview.gui.VamsasApplication(this, file, - url.toExternalForm()); - } catch (Exception ex) - { - jalview.bin.Cache.log.error( - "Failed to create new vamsas session from contents of URL " - + url, - ex); - return false; - } - setupVamsasConnectedGui(); - v_client.initial_update(); // TODO: thread ? - return v_client.inSession(); - } - - /** - * import file into a new vamsas session (uses jalview.gui.VamsasApplication) - * - * @param file - * @return true if import was a success and a session was started. - */ - public boolean vamsasImport(File file) - { - if (v_client != null) - { - - jalview.bin.Cache.log.error( - "Implementation error - load session from a running session is not supported."); - return false; - } - - setProgressBar(MessageManager.formatMessage( - "status.importing_vamsas_session_from", new Object[] - { file.getName() }), file.hashCode()); - try - { - v_client = new jalview.gui.VamsasApplication(this, file, null); - } catch (Exception ex) - { - setProgressBar(MessageManager.formatMessage( - "status.importing_vamsas_session_from", new Object[] - { file.getName() }), file.hashCode()); - jalview.bin.Cache.log.error( - "New vamsas session from existing session file failed:", ex); - return false; - } - setupVamsasConnectedGui(); - v_client.initial_update(); // TODO: thread ? - setProgressBar(MessageManager.formatMessage( - "status.importing_vamsas_session_from", new Object[] - { file.getName() }), file.hashCode()); - return v_client.inSession(); - } - - public boolean joinVamsasSession(String mysesid) - { - if (v_client != null) - { - throw new Error(MessageManager - .getString("error.try_join_vamsas_session_another")); - } - if (mysesid == null) - { - throw new Error( - MessageManager.getString("error.invalid_vamsas_session_id")); - } - v_client = new VamsasApplication(this, mysesid); - setupVamsasConnectedGui(); - v_client.initial_update(); - return (v_client.inSession()); - } - - @Override - public void vamsasStart_actionPerformed(ActionEvent e) - { - if (v_client == null) - { - // Start a session. - // we just start a default session for moment. - /* - * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache. - * getProperty("LAST_DIRECTORY")); - * - * chooser.setFileView(new JalviewFileView()); - * chooser.setDialogTitle("Load Vamsas file"); - * chooser.setToolTipText("Import"); - * - * int value = chooser.showOpenDialog(this); - * - * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new - * jalview.gui.VamsasApplication(this, chooser.getSelectedFile()); - */ - v_client = new VamsasApplication(this); - setupVamsasConnectedGui(); - v_client.initial_update(); // TODO: thread ? - } - else - { - // store current data in session. - v_client.push_update(); // TODO: thread - } - } - - protected void setupVamsasConnectedGui() - { - vamsasStart.setText(MessageManager.getString("label.session_update")); - vamsasSave.setVisible(true); - vamsasStop.setVisible(true); - vamsasImport.setVisible(false); // Document import to existing session is - // not possible for vamsas-client-1.0. - } - - protected void setupVamsasDisconnectedGui() - { - vamsasSave.setVisible(false); - vamsasStop.setVisible(false); - vamsasImport.setVisible(true); - vamsasStart - .setText(MessageManager.getString("label.new_vamsas_session")); - } - - @Override - public void vamsasStop_actionPerformed(ActionEvent e) - { - if (v_client != null) - { - v_client.end_session(); - v_client = null; - setupVamsasDisconnectedGui(); - } - } - - protected void buildVamsasStMenu() - { - if (v_client == null) - { - String[] sess = null; - try - { - sess = VamsasApplication.getSessionList(); - } catch (Exception e) - { - jalview.bin.Cache.log.warn("Problem getting current sessions list.", - e); - sess = null; - } - if (sess != null) - { - jalview.bin.Cache.log.debug( - "Got current sessions list: " + sess.length + " entries."); - VamsasStMenu.removeAll(); - for (int i = 0; i < sess.length; i++) - { - JMenuItem sessit = new JMenuItem(); - sessit.setText(sess[i]); - sessit.setToolTipText(MessageManager - .formatMessage("label.connect_to_session", new Object[] - { sess[i] })); - final Desktop dsktp = this; - final String mysesid = sess[i]; - sessit.addActionListener(new ActionListener() - { - - @Override - public void actionPerformed(ActionEvent e) + if (af.featureSettings != null && af.featureSettings.isOpen()) { - if (dsktp.v_client == null) + if (source.featureSettings == null) { - Thread rthr = new Thread(new Runnable() - { - - @Override - public void run() - { - dsktp.v_client = new VamsasApplication(dsktp, mysesid); - dsktp.setupVamsasConnectedGui(); - dsktp.v_client.initial_update(); - } - - }); - rthr.start(); + // preserve the feature settings geometry for this frame + source.featureSettings = af.featureSettings; + source.setFeatureSettingsGeometry( + af.getFeatureSettingsGeometry()); + } + else + { + // close it and forget + af.featureSettings.close(); } } - }); - VamsasStMenu.add(sessit); - } - // don't show an empty menu. - VamsasStMenu.setVisible(sess.length > 0); - - } - else - { - jalview.bin.Cache.log.debug("No current vamsas sessions."); - VamsasStMenu.removeAll(); - VamsasStMenu.setVisible(false); - } - } - else - { - // Not interested in the content. Just hide ourselves. - VamsasStMenu.setVisible(false); - } - } - - @Override - public void vamsasSave_actionPerformed(ActionEvent e) - { - // TODO: JAL-3048 not needed for Jalview-JS - - if (v_client != null) - { - // TODO: VAMSAS DOCUMENT EXTENSION is VDJ - JalviewFileChooser chooser = new JalviewFileChooser("vdj", - "Vamsas Document"); - - chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.save_vamsas_document_archive")); - - int value = chooser.showSaveDialog(this); - - if (value == JalviewFileChooser.APPROVE_OPTION) - { - java.io.File choice = chooser.getSelectedFile(); - JPanel progpanel = addProgressPanel(MessageManager - .formatMessage("label.saving_vamsas_doc", new Object[] - { choice.getName() })); - Cache.setProperty("LAST_DIRECTORY", choice.getParent()); - String warnmsg = null; - String warnttl = null; - try - { - v_client.vclient.storeDocument(choice); - } catch (Error ex) - { - warnttl = "Serious Problem saving Vamsas Document"; - warnmsg = ex.toString(); - jalview.bin.Cache.log - .error("Error Whilst saving document to " + choice, ex); - - } catch (Exception ex) - { - warnttl = "Problem saving Vamsas Document."; - warnmsg = ex.toString(); - jalview.bin.Cache.log.warn( - "Exception Whilst saving document to " + choice, ex); - - } - removeProgressPanel(progpanel); - if (warnmsg != null) - { - JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(), - - warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE); + af.alignPanels.clear(); + af.closeMenuItem_actionPerformed(true); + } } } - } - } - - JPanel vamUpdate = null; - - /** - * hide vamsas user gui bits when a vamsas document event is being handled. - * - * @param b - * true to hide gui, false to reveal gui - */ - public void setVamsasUpdate(boolean b) - { - Cache.log.debug("Setting gui for Vamsas update " - + (b ? "in progress" : "finished")); - - if (vamUpdate != null) + // refresh the feature setting UI for the source frame if it exists + if (source.featureSettings != null + && source.featureSettings.isOpen()) { - this.removeProgressPanel(vamUpdate); + source.showFeatureSettingsUI(); } - if (b) - { - vamUpdate = this.addProgressPanel( - MessageManager.getString("label.updating_vamsas_session")); - } - vamsasStart.setVisible(!b); - vamsasStop.setVisible(!b); - vamsasSave.setVisible(!b); } public JInternalFrame[] getAllFrames() @@ -2692,7 +2330,7 @@ public class Desktop extends GDesktop { if (Jalview.isHeadlessMode()) { - // Desktop.getDesktop() is null in headless mode + // Desktop.getDesktopPane() is null in headless mode return new AlignFrame[] { Jalview.getCurrentAlignFrame() }; } @@ -2776,7 +2414,7 @@ public class Desktop extends GDesktop openGroovyConsole(); } catch (Exception ex) { - jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex); + Cache.log.error("Groovy Shell Creation failed.", ex); JvOptionPane.showInternalMessageDialog(desktopPane, MessageManager.getString("label.couldnt_create_groovy_shell"), @@ -2837,7 +2475,7 @@ public class Desktop extends GDesktop { getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx()), "Quit"); getRootPane().getActionMap().put("Quit", new AbstractAction() { @@ -2888,7 +2526,7 @@ public class Desktop extends GDesktop @Override public void setProgressBar(String message, long id) { - Platform.timeCheck("Desktop " + message, Platform.TIME_MARK); + // Platform.timeCheck("Desktop " + message, Platform.TIME_MARK); if (progressBars == null) { @@ -2896,18 +2534,18 @@ public class Desktop extends GDesktop progressBarHandlers = new Hashtable<>(); } - if (progressBars.get(new Long(id)) != null) + if (progressBars.get(Long.valueOf(id)) != null) { - JPanel panel = progressBars.remove(new Long(id)); - if (progressBarHandlers.contains(new Long(id))) + JPanel panel = progressBars.remove(Long.valueOf(id)); + if (progressBarHandlers.contains(Long.valueOf(id))) { - progressBarHandlers.remove(new Long(id)); + progressBarHandlers.remove(Long.valueOf(id)); } removeProgressPanel(panel); } else { - progressBars.put(new Long(id), addProgressPanel(message)); + progressBars.put(Long.valueOf(id), addProgressPanel(message)); } } @@ -2922,13 +2560,13 @@ public class Desktop extends GDesktop final IProgressIndicatorHandler handler) { if (progressBarHandlers == null - || !progressBars.containsKey(new Long(id))) + || !progressBars.containsKey(Long.valueOf(id))) { throw new Error(MessageManager.getString( "error.call_setprogressbar_before_registering_handler")); } - progressBarHandlers.put(new Long(id), handler); - final JPanel progressPanel = progressBars.get(new Long(id)); + progressBarHandlers.put(Long.valueOf(id), handler); + final JPanel progressPanel = progressBars.get(Long.valueOf(id)); if (handler.canCancel()) { JButton cancel = new JButton( @@ -2989,12 +2627,6 @@ public class Desktop extends GDesktop return null; } - public VamsasApplication getVamsasApplication() - { - return v_client; - - } - /** * flag set if jalview GUI is being operated programmatically */ @@ -3035,8 +2667,8 @@ public class Desktop extends GDesktop // todo: changesupport handlers need to be transferred if (discoverer == null) { - discoverer = Discoverer.getInstance(); - // register PCS handler for getDesktop(). + discoverer = jalview.ws.jws1.Discoverer.getInstance(); + // register PCS handler for getDesktopPane(). discoverer.addPropertyChangeListener(changeSupport); } // JAL-940 - disabled JWS1 service configuration - always start discoverer @@ -3175,13 +2807,13 @@ public class Desktop extends GDesktop { try { - if (progress != null) + if (progress != null && !Platform.isJS()) { progress.setProgressBar(MessageManager .formatMessage("status.opening_params", new Object[] { url }), this.hashCode()); } - BrowserLauncher.openURL(url); + Platform.openURL(url); } catch (Exception ex) { JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(), @@ -3192,7 +2824,7 @@ public class Desktop extends GDesktop ex.printStackTrace(); } - if (progress != null) + if (progress != null && !Platform.isJS()) { progress.setProgressBar(null, this.hashCode()); } @@ -3254,13 +2886,14 @@ public class Desktop extends GDesktop /** * flag indicating if dialogExecutor should try to acquire a permit */ - volatile boolean dialogPause = true; + private volatile boolean dialogPause = true; /** * pause the queue */ - java.util.concurrent.Semaphore block = new Semaphore(0); + private java.util.concurrent.Semaphore block = new Semaphore(0); + // BH was static private groovy.ui.Console groovyConsole; public StructureViewer lastTargetedView; @@ -3286,6 +2919,7 @@ public class Desktop extends GDesktop { } } + // BH! Q: do we mean System.headless ? or "nogui/nodisplay" headless? if (Jalview.isHeadlessMode()) { return; @@ -3768,4 +3402,39 @@ public class Desktop extends GDesktop return result; } + + + public MyDesktopPane desktopPane; + + /** + * Get the instance of the JDesktopPane from the application-local Desktop + * (JFrame) instance + * + * The key here is that the Java application can have multiple static + * instances of the desktop JFrame because those instances are sandboxed, but + * the SwingJS JFrames will be in the same VM-like space. So we need + * application singletons, at least for JavaScript. + * + * @return + */ + public static MyDesktopPane getDesktopPane() + { + Desktop desktop = Desktop.getInstance(); + return desktop == null ? null : desktop.desktopPane; + } + + /** + * Answers an 'application scope' singleton instance of this class. Separate + * SwingJS 'applets' running in the same browser page will each have a + * distinct instance of Desktop. + * + * @return + */ + public static Desktop getInstance() + { + return Jalview.isHeadlessMode() ? null + : (Desktop) ApplicationSingletonProvider + .getInstance(Desktop.class); + } + }