Merge branch 'Jalview-BH/JAL-3026' into tasks/JAL-3033_jalviewjs_ant
[jalview.git] / src / jalview / gui / Desktop.java
index 8be4eac..b4b0cdb 100644 (file)
@@ -69,6 +69,7 @@ import java.awt.dnd.DropTargetEvent;
 import java.awt.dnd.DropTargetListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -92,10 +93,13 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;
 
 import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.DefaultDesktopManager;
 import javax.swing.DesktopManager;
+import javax.swing.InputMap;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -378,65 +382,39 @@ public class Desktop extends jalview.jbgui.GDesktop
       setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
               900, 650);
     }
-    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"));
-
-    showConsole(showjconsole);
-
-    showNews.setVisible(false);
+    /**
+     * BH 2018
+     * 
+     * @j2sNative
+     */
+    {
 
-    experimentalFeatures.setSelected(showExperimental());
+      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"));
 
-    getIdentifiersOrgData();
+      showConsole(showjconsole);
 
-    checkURLLinks();
+      showNews.setVisible(false);
 
-    this.addWindowListener(new WindowAdapter()
-    {
-      @Override
-      public void windowClosing(WindowEvent evt)
-      {
-        quit();
-      }
-    });
+      experimentalFeatures.setSelected(showExperimental());
 
-    MouseAdapter ma;
-    this.addMouseListener(ma = new MouseAdapter()
-    {
-      @Override
-      public void mousePressed(MouseEvent evt)
-      {
-        if (evt.isPopupTrigger()) // Mac
-        {
-          showPasteMenu(evt.getX(), evt.getY());
-        }
-      }
+      getIdentifiersOrgData();
 
-      @Override
-      public void mouseReleased(MouseEvent evt)
-      {
-        if (evt.isPopupTrigger()) // Windows
-        {
-          showPasteMenu(evt.getX(), evt.getY());
-        }
-      }
-    });
-    desktop.addMouseListener(ma);
+      checkURLLinks();
 
     this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
     // Spawn a thread that shows the splashscreen
+
     SwingUtilities.invokeLater(new Runnable()
     {
       @Override
@@ -474,6 +452,41 @@ public class Desktop extends jalview.jbgui.GDesktop
               }
 
             });
+
+    } // end BH 2018 ignore
+
+    this.addWindowListener(new WindowAdapter()
+    {
+      @Override
+      public void windowClosing(WindowEvent evt)
+      {
+        quit();
+      }
+    });
+
+    MouseAdapter ma;
+    this.addMouseListener(ma = new MouseAdapter()
+    {
+      @Override
+      public void mousePressed(MouseEvent evt)
+      {
+        if (evt.isPopupTrigger()) // Mac
+        {
+          showPasteMenu(evt.getX(), evt.getY());
+        }
+      }
+
+      @Override
+      public void mouseReleased(MouseEvent evt)
+      {
+        if (evt.isPopupTrigger()) // Windows
+        {
+          showPasteMenu(evt.getX(), evt.getY());
+        }
+      }
+    });
+    desktop.addMouseListener(ma);
+
   }
 
   /**
@@ -513,20 +526,28 @@ public class Desktop extends jalview.jbgui.GDesktop
 
   public void checkForNews()
   {
+
+    /**
+     * BH 2018
+     * 
+     * @j2sNative
+     */
+    {
     final Desktop me = this;
     // Thread off the news reader, in case there are connection problems.
     addDialogThread(new Runnable()
     {
-      @Override
-      public void run()
-      {
-        Cache.log.debug("Starting news thread.");
+        @Override
+        public void run()
+        {
+          Cache.log.debug("Starting news thread.");
 
-        jvnews = new BlogReader(me);
-        showNews.setVisible(true);
-        Cache.log.debug("Completed news thread.");
-      }
+          jvnews = new BlogReader(me);
+          showNews.setVisible(true);
+          Cache.log.debug("Completed news thread.");
+        }
     });
+    }
   }
 
   public void getIdentifiersOrgData()
@@ -560,6 +581,12 @@ public class Desktop extends jalview.jbgui.GDesktop
 
   void showNews(boolean visible)
   {
+    /**
+     * BH 2018
+     * 
+     * @j2sNative
+     * 
+     */
     {
       Cache.log.debug((visible ? "Showing" : "Hiding") + " news.");
       showNews.setSelected(visible);
@@ -643,7 +670,8 @@ public class Desktop extends jalview.jbgui.GDesktop
 
   private void doVamsasClientCheck()
   {
-    if (jalview.bin.Cache.vamsasJarsPresent())
+    if (/** @j2sNative false && */ // BH 2018
+    jalview.bin.Cache.vamsasJarsPresent())
     {
       setupVamsasDisconnectedGui();
       VamsasMenu.setVisible(true);
@@ -852,7 +880,8 @@ public class Desktop extends jalview.jbgui.GDesktop
     frame.setResizable(resizable);
     frame.setMaximizable(resizable);
     frame.setIconifiable(resizable);
-    frame.setOpaque(false);
+    frame.setOpaque(/** @j2sNative true || */
+            false);
 
     if (frame.getX() < 1 && frame.getY() < 1)
     {
@@ -903,8 +932,6 @@ public class Desktop extends jalview.jbgui.GDesktop
           menuItem.removeActionListener(menuItem.getActionListeners()[0]);
         }
         windowMenu.remove(menuItem);
-
-        System.gc();
       };
     });
 
@@ -924,6 +951,8 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
     });
 
+    setKeyBindings(frame);
+
     desktop.add(frame);
 
     windowMenu.add(menuItem);
@@ -943,6 +972,42 @@ public class Desktop extends jalview.jbgui.GDesktop
     }
   }
 
+  /**
+   * Add key bindings to a JInternalFrame so that Ctrl-W and Cmd-W will close
+   * the window
+   * 
+   * @param frame
+   */
+  private static void setKeyBindings(JInternalFrame frame)
+  {
+    @SuppressWarnings("serial")
+    final Action closeAction = new AbstractAction()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        frame.dispose();
+      }
+    };
+
+    /*
+     * set up key bindings for Ctrl-W and Cmd-W, with the same (Close) action
+     */
+    KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            InputEvent.CTRL_DOWN_MASK);
+    KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
+
+    InputMap inputMap = frame
+            .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    String ctrlW = ctrlWKey.toString();
+    inputMap.put(ctrlWKey, ctrlW);
+    inputMap.put(cmdWKey, ctrlW);
+
+    ActionMap actionMap = frame.getActionMap();
+    actionMap.put(ctrlW, closeAction);
+  }
+
   @Override
   public void lostOwnership(Clipboard clipboard, Transferable contents)
   {
@@ -1103,8 +1168,8 @@ public class Desktop extends jalview.jbgui.GDesktop
     // for viewing
     JLabel label = new JLabel(
             MessageManager.getString("label.input_file_url"));
-    final JComboBox history = new JComboBox();
 
+    JComboBox history = new JComboBox();
     JPanel panel = new JPanel(new GridLayout(2, 1));
     panel.add(label);
     panel.add(history);
@@ -1126,66 +1191,28 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
     }
 
-    int reply = JvOptionPane.showInternalConfirmDialog(desktop, panel,
-            MessageManager.getString("label.input_alignment_from_url"),
-            JvOptionPane.OK_CANCEL_OPTION);
+    // BH 2018 -- providing a callback for SwingJS
+    // dialogOption is just a simple way to provide
+    // context for the modal-like response.
+    // The only requirement is that desktop implement
+    // PropertyChangeListener, which is used already in Java
+    // for changes in input value and such within the dialogs.
 
-    if (reply != JvOptionPane.OK_OPTION)
-    {
-      return;
-    }
-
-    String url = history.getSelectedItem().toString();
-
-    if (url.toLowerCase().endsWith(".jar"))
-    {
-      if (viewport != null)
-      {
-        new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
-                FileFormat.Jalview);
-      }
-      else
-      {
-        new FileLoader().LoadFile(url, DataSourceType.URL,
-                FileFormat.Jalview);
-      }
-    }
-    else
-    {
-      FileFormatI format = null;
-      try
-      {
-        format = new IdentifyFile().identify(url, DataSourceType.URL);
-      } catch (FileFormatException e)
-      {
-        // TODO revise error handling, distinguish between
-        // URL not found and response not valid
-      }
+    String dialogOption = "label.input_alignment_from_url";
+    desktop.dialogData = new Object[] { dialogOption, viewport, history };
+    desktop.onDialogReturn(
+            JvOptionPane.showInternalConfirmDialog(desktop, panel,
+            MessageManager.getString(dialogOption),
+            JvOptionPane.OK_CANCEL_OPTION));
 
-      if (format == null)
-      {
-        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                MessageManager.formatMessage("label.couldnt_locate",
-                        new Object[]
-                        { url }),
-                MessageManager.getString("label.url_not_found"),
-                JvOptionPane.WARNING_MESSAGE);
+    // no code may follow this, as SwingJS will not block
+    // callback in JavaScript comes via a property change event,
+    // thus going into desktop.onDialogReturn(int) just the same as
+    // in Java.
 
-        return;
-      }
-
-      if (viewport != null)
-      {
-        new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
-                format);
-      }
-      else
-      {
-        new FileLoader().LoadFile(url, DataSourceType.URL, format);
-      }
-    }
   }
 
+
   /**
    * Opens the CutAndPaste window for the user to paste an alignment in to
    * 
@@ -1392,7 +1419,6 @@ public class Desktop extends jalview.jbgui.GDesktop
     {
       ssm.resetAll();
     }
-    System.gc();
   }
 
   @Override
@@ -1462,11 +1488,14 @@ public class Desktop extends jalview.jbgui.GDesktop
    */
   void showConsole(boolean selected)
   {
-    showConsole.setSelected(selected);
     // TODO: decide if we should update properties file
-    Cache.setProperty("SHOW_JAVA_CONSOLE",
-            Boolean.valueOf(selected).toString());
-    jconsole.setVisible(selected);
+    if (jconsole != null) // BH 2018
+    {
+      showConsole.setSelected(selected);
+      Cache.setProperty("SHOW_JAVA_CONSOLE",
+              Boolean.valueOf(selected).toString());
+      jconsole.setVisible(selected);
+    }
   }
 
   void reorderAssociatedWindows(boolean minimize, boolean close)
@@ -2326,7 +2355,8 @@ public class Desktop extends jalview.jbgui.GDesktop
       @Override
       public void run()
       {
-        if (Cache.getDefault("CHECKURLLINKS", true))
+        if (/** @j2sNative false && */ // BH 2018
+        Cache.getDefault("CHECKURLLINKS", true))
         {
           // check what the actual links are - if it's just the default don't
           // bother with the warning
@@ -2404,9 +2434,148 @@ public class Desktop extends jalview.jbgui.GDesktop
    * 
    * @author AMW
    */
-  public class MyDesktopPane extends JDesktopPane implements Runnable
+  public class MyDesktopPane extends JDesktopPane
+          implements Runnable, PropertyChangeListener
   {
 
+    public Object[] dialogData;
+
+    // @Override
+    @Override
+    public void propertyChange(PropertyChangeEvent event)
+    {
+      Object val = event.getNewValue();
+      String name = event.getPropertyName();
+      System.out.println(name);
+      switch (event.getSource().getClass().getName())
+      {
+      case "javax.swing.JOptionPane":
+        switch (name)
+        {
+        case "inputValue":
+          onDialogReturn(val);
+          return;
+        case "value":
+          if (val instanceof Integer)
+          {
+            onDialogReturn(((Integer) val).intValue());
+          }
+          else
+          {
+            onDialogReturn(val);
+          }
+          return;
+        }
+        break;
+      case "javax.swing.ColorChooserDialog":
+        switch (name)
+        {
+        case "SelectedColor":
+          onDialogReturn(val);
+          return;
+        }
+        break;
+      case "javax.swing.JFileChooser":
+        switch (name)
+        {
+        case "SelectedFile":
+          File file = (File) val;
+          byte[] array = (val == null ? null
+                  : /** @j2sNative file._bytes || */
+                  null);
+          onDialogReturn("fileName is '" + file.getName() + "'\n\n"
+                  + new String(array));
+          return;
+        }
+        break;
+      }
+      System.out.println(event.getSource().getClass().getName() + " "
+              + event.getPropertyName() + ": " + event.getNewValue());
+    }
+
+    // JSCOmponent.DialogCaller interface
+    private void onDialogReturn(Object value)
+    {
+      System.out.println("not implemented");
+    }
+
+    // JSCOmponent.DialogCaller interface
+    void onDialogReturn(int value)
+    {
+      if (value != Math.floor(value))
+      {
+        // in JavaScript, this will be NaN, oddly enough
+        return;
+      }
+
+      switch ((String) dialogData[0])
+      {
+      case "label.input_alignment_from_url":
+        // reconstruct the parameter data
+        int reply = value;
+        AlignViewport viewport = (AlignViewport) dialogData[1];
+        JComboBox history = (JComboBox) dialogData[2];
+        // the rest of this is unchangaed
+        if (reply != JvOptionPane.OK_OPTION)
+        {
+          return;
+        }
+
+        String url = history.getSelectedItem().toString();
+
+        if (url.toLowerCase().endsWith(".jar"))
+        {
+          if (viewport != null)
+          {
+            new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
+                    FileFormat.Jalview);
+          }
+          else
+          {
+            new FileLoader().LoadFile(url, DataSourceType.URL,
+                    FileFormat.Jalview);
+          }
+        }
+        else
+        {
+          FileFormatI format = null;
+          try
+          {
+            format = new IdentifyFile().identify(url, DataSourceType.URL);
+          } catch (FileFormatException e)
+          {
+            // TODO revise error handling, distinguish between
+            // URL not found and response not valid
+          }
+
+          if (format == null)
+          {
+            JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    MessageManager.formatMessage("label.couldnt_locate",
+                            new Object[]
+                    { url }),
+                    MessageManager.getString("label.url_not_found"),
+                    JvOptionPane.WARNING_MESSAGE);
+
+            return;
+          }
+
+          if (viewport != null)
+          {
+            new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
+                    format);
+          }
+          else
+          {
+            new FileLoader().LoadFile(url, DataSourceType.URL, format);
+          }
+        }
+
+        break;
+      }
+
+    }
+
     private static final float ONE_MB = 1048576f;
 
     boolean showMemoryUsage = false;