JAL-3633 Apply (proxy) button enabled when needed
[jalview.git] / src / jalview / gui / Preferences.java
index 6a558d5..0e04117 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
-import jalview.bin.Cache;
-import jalview.bin.Jalview;
-import jalview.gui.Help.HelpId;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.FileFormatI;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.jbgui.GPreferences;
-import jalview.jbgui.GSequenceLink;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ColourSchemes;
-import jalview.schemes.ResidueColourScheme;
-import jalview.urls.UrlLinkTableModel;
-import jalview.urls.api.UrlProviderFactoryI;
-import jalview.urls.api.UrlProviderI;
-import jalview.urls.desktop.DesktopUrlProviderFactory;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.util.UrlConstants;
-import jalview.ws.sifts.SiftsSettings;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
@@ -73,6 +51,29 @@ import javax.swing.table.TableModel;
 import javax.swing.table.TableRowSorter;
 
 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.bin.Cache;
+import jalview.ext.pymol.PymolManager;
+import jalview.gui.Help.HelpId;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
+import jalview.io.FileFormatI;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+import jalview.jbgui.GPreferences;
+import jalview.jbgui.GSequenceLink;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
+import jalview.urls.UrlLinkTableModel;
+import jalview.urls.api.UrlProviderFactoryI;
+import jalview.urls.api.UrlProviderI;
+import jalview.urls.desktop.DesktopUrlProviderFactory;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.util.UrlConstants;
+import jalview.ws.sifts.SiftsSettings;
 
 /**
  * DOCUMENT ME!
@@ -80,6 +81,10 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
  * @author $author$
  * @version $Revision$
  */
+/*
+ * for merge with Jalview-JS
+ public class Preferences extends GPreferences implements ApplicationSingletonI
+ */
 public class Preferences extends GPreferences
 {
   public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
@@ -104,6 +109,10 @@ public class Preferences extends GPreferences
 
   public static final String CHIMERA_PATH = "CHIMERA_PATH";
 
+  public static final String CHIMERAX_PATH = "CHIMERAX_PATH";
+
+  public static final String PYMOL_PATH = "PYMOL_PATH";
+
   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
 
   public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
@@ -122,6 +131,10 @@ public class Preferences extends GPreferences
 
   private static final int MAX_FONT_SIZE = 30;
 
+  private String previousProxyType;
+
+  private static Preferences INSTANCE = null; // add "final"
+
   /**
    * Holds name and link separated with | character. Sequence ID must be
    * $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$
@@ -181,15 +194,58 @@ public class Preferences extends GPreferences
   private OptionsParam textOpt = new OptionsParam(
           MessageManager.getString("action.text"), "Text");
 
+  // get singleton Preferences instance
+  public static Preferences getInstance()
+  {
+    if (INSTANCE == null || INSTANCE.frame == null
+            || INSTANCE.frame.isClosed())
+    {
+      INSTANCE = new Preferences();
+    }
+    return INSTANCE;
+
+    /*
+     * Replace code with the following for Jalvew-JS
+    Preferences INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
+    if (INSTANCE == null || INSTANCE.frame == null
+            || INSTANCE.frame.isClosed())
+    {
+      ApplicationSingletonProvider.remove(Preferences.class);
+      INSTANCE = ApplicationSingletonProvider.getInstance(Preferences.class);
+    }
+    return INSTANCE;
+    */
+  }
+
+  public static void openPreferences()
+  {
+    openPreferences(0, null);
+  }
+
+  public static void openPreferences(int selectTab, String message)
+  {
+    Preferences p = getInstance();
+    p.selectTab(selectTab);
+    p.setMessage(message);
+    p.frame.show();
+    p.frame.moveToFront();
+    p.frame.grabFocus();
+  }
+
   /**
    * Creates a new Preferences object.
    */
-  public Preferences()
+  private Preferences()
   {
     super();
     frame = new JInternalFrame();
     frame.setContentPane(this);
-    if (!Jalview.isJS())
+    if (!Platform.isJS())
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
+     */
     {
       wsPrefs = new WsPreferences();
       wsTab.add(wsPrefs, BorderLayout.CENTER);
@@ -254,7 +310,7 @@ public class Preferences extends GPreferences
     fontStyleCB.setSelectedItem(
             Cache.getDefault("FONT_STYLE", Font.PLAIN + ""));
 
-    smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", false));
+    smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", true));
     scaleProteinToCdna
             .setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA, false));
 
@@ -328,10 +384,10 @@ public class Preferences extends GPreferences
     gapLabel.setEnabled(!useLegacyGap.isSelected());
     gapColour.setEnabled(!useLegacyGap.isSelected());
     showHiddenAtStart
-            .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, true));
+            .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, false));
 
     /*
-     * Set Structure tab defaults.
+     * Set Structure tab defaults
      */
     final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, false);
     structFromPdb.setSelected(structSelected);
@@ -341,15 +397,52 @@ public class Preferences extends GPreferences
     addSecondaryStructure.setEnabled(structSelected);
     addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false));
     addTempFactor.setEnabled(structSelected);
-    structViewer.setSelectedItem(
-            Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name()));
-    chimeraPath.setText(Cache.getDefault(CHIMERA_PATH, ""));
-    chimeraPath.addActionListener(new ActionListener()
+
+    /*
+     * set choice of structure viewer, and path if saved as a preference;
+     * default to Jmol (first choice) if an unexpected value is found
+     */
+    String viewerType = Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name());
+    structViewer.setSelectedItem(viewerType);
+    String viewerPath = "";
+    ViewerType type = null;
+    try
+    {
+      type = ViewerType.valueOf(viewerType);
+      switch (type)
+      {
+      case JMOL:
+        break;
+      case CHIMERA:
+        viewerPath = Cache.getDefault(CHIMERA_PATH, "");
+        break;
+      case CHIMERAX:
+        viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
+        break;
+      case PYMOL:
+        viewerPath = Cache.getDefault(PYMOL_PATH, "");
+        break;
+      }
+    } catch (IllegalArgumentException e)
+    {
+      Cache.log.error("Unknown structure viewer type: " + viewerType
+              + ", defaulting to Jmol");
+      type = ViewerType.JMOL;
+    }
+    structureViewerPath.setText(viewerPath);
+
+    structureViewerPath.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        validateChimeraPath();
+        if (validateViewerPath())
+        {
+          Cache.setProperty(structViewer.getSelectedItem()
+                  .equals(ViewerType.CHIMERAX.name())
+                  ? CHIMERAX_PATH
+                  : CHIMERA_PATH, structureViewerPath.getText());
+        }
       }
     });
 
@@ -489,10 +582,36 @@ public class Preferences extends GPreferences
       }
     }
 
-    useProxy.setSelected(Cache.getDefault("USE_PROXY", false));
-    useProxy_actionPerformed(); // make sure useProxy is correctly initialised
-    proxyServerTB.setText(Cache.getDefault("PROXY_SERVER", ""));
-    proxyPortTB.setText(Cache.getDefault("PROXY_PORT", ""));
+    String proxyTypeString = Cache.getDefault("USE_PROXY", "false");
+    previousProxyType = proxyTypeString;
+    switch (proxyTypeString)
+    {
+    case Cache.PROXYTYPE_NONE:
+      proxyType.setSelected(noProxy.getModel(), true);
+      break;
+    case Cache.PROXYTYPE_SYSTEM:
+      proxyType.setSelected(systemProxy.getModel(), true);
+      break;
+    case Cache.PROXYTYPE_CUSTOM:
+      proxyType.setSelected(customProxy.getModel(), true);
+      break;
+    default:
+      Cache.log.warn(
+              "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): "
+                      + proxyTypeString);
+    }
+    proxyServerHttpTB.setText(Cache.getDefault("PROXY_SERVER", ""));
+    proxyPortHttpTB.setText(Cache.getDefault("PROXY_PORT", ""));
+    proxyServerHttpsTB.setText(Cache.getDefault("PROXY_SERVER_HTTPS", ""));
+    proxyPortHttpsTB.setText(Cache.getDefault("PROXY_PORT_HTTPS", ""));
+    proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false));
+    proxyAuthUsernameTB
+            .setText(Cache.getDefault("PROXY_AUTH_USERNAME", ""));
+    // we are not storing or retrieving proxy password from .jalview_properties
+    proxyAuthPasswordPB.setText(Cache.proxyAuthPassword == null ? ""
+            : new String(Cache.proxyAuthPassword));
+    setCustomProxyEnabled();
+    applyProxyButtonEnabled(false);
 
     defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", ""));
 
@@ -536,6 +655,12 @@ public class Preferences extends GPreferences
 
     annotations_actionPerformed(null); // update the display of the annotation
                                        // settings
+    
+    
+    /*
+     * Set Backups tab defaults
+     */
+    loadLastSavedBackupsOptions();
   }
 
   /**
@@ -555,7 +680,7 @@ public class Preferences extends GPreferences
     /*
      * JalviewJS doesn't support Lineart so force it to Text
      */
-    String defaultOption = Jalview.isJS() ? "Text"
+    String defaultOption = Platform.isJS() ? "Text"
             : Cache.getDefault(propertyKey, "Prompt each time");
     if (defaultOption.equalsIgnoreCase("Text"))
     {
@@ -585,6 +710,11 @@ public class Preferences extends GPreferences
       return;
     }
 
+    /* 
+     * Set proxy settings first (to be before web services refresh)
+     */
+    saveProxySettings();
+
     /*
      * Save Visual settings
      */
@@ -695,9 +825,22 @@ public class Preferences extends GPreferences
             Boolean.toString(useRnaView.isSelected()));
     Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
             Boolean.toString(structFromPdb.isSelected()));
+    String viewer = structViewer.getSelectedItem().toString();
+    String viewerPath = structureViewerPath.getText();
     Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY,
-            structViewer.getSelectedItem().toString());
-    Cache.setOrRemove(CHIMERA_PATH, chimeraPath.getText());
+            viewer);
+    if (viewer.equals(ViewerType.CHIMERA.name()))
+    {
+      Cache.setOrRemove(CHIMERA_PATH, viewerPath);
+    }
+    else if (viewer.equals(ViewerType.CHIMERAX.name()))
+    {
+      Cache.setOrRemove(CHIMERAX_PATH, viewerPath);
+    }
+    else if (viewer.equals(ViewerType.PYMOL.name()))
+    {
+      Cache.setOrRemove(PYMOL_PATH, viewerPath);
+    }
     Cache.applicationProperties.setProperty("MAP_WITH_SIFTS",
             Boolean.toString(siftsMapping.isSelected()));
     SiftsSettings.setMapWithSifts(siftsMapping.isSelected());
@@ -715,6 +858,8 @@ public class Preferences extends GPreferences
     /*
      * Save Connections settings
      */
+    // Proxy settings set first (to catch web services)
+
     Cache.setOrRemove("DEFAULT_BROWSER", defaultBrowser.getText());
 
     jalview.util.BrowserLauncher.resetBrowser();
@@ -745,23 +890,6 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("DEFAULT_URL",
             sequenceUrlLinks.getPrimaryUrlId());
 
-    Cache.applicationProperties.setProperty("USE_PROXY",
-            Boolean.toString(useProxy.isSelected()));
-
-    Cache.setOrRemove("PROXY_SERVER", proxyServerTB.getText());
-
-    Cache.setOrRemove("PROXY_PORT", proxyPortTB.getText());
-
-    if (useProxy.isSelected())
-    {
-      System.setProperty("http.proxyHost", proxyServerTB.getText());
-      System.setProperty("http.proxyPort", proxyPortTB.getText());
-    }
-    else
-    {
-      System.setProperty("http.proxyHost", "");
-      System.setProperty("http.proxyPort", "");
-    }
     Cache.setProperty("VERSION_CHECK",
             Boolean.toString(versioncheck.isSelected()));
     if (Cache.getProperty("USAGESTATS") != null || usagestats.isSelected())
@@ -820,10 +948,34 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("PAD_GAPS",
             Boolean.toString(padGaps.isSelected()));
 
-    if (!Jalview.isJS())
+    if (!Platform.isJS())
     {
       wsPrefs.updateAndRefreshWsMenuConfig(false);
     }
+
+    /*
+     * Save Backups settings
+     */
+    Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
+            Boolean.toString(enableBackupFiles.isSelected()));
+    int preset = getComboIntStringKey(backupfilesPresetsCombo);
+    Cache.applicationProperties.setProperty(BackupFiles.NS + "_PRESET", Integer.toString(preset));
+
+    if (preset == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
+    {
+      BackupFilesPresetEntry customBFPE = getBackupfilesCurrentEntry();
+      BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
+              BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM, customBFPE);
+      Cache.applicationProperties
+              .setProperty(BackupFilesPresetEntry.CUSTOMCONFIG,
+                      customBFPE.toString());
+    }
+
+    BackupFilesPresetEntry savedBFPE = BackupFilesPresetEntry.backupfilesPresetEntriesValues
+            .get(preset);
+    Cache.applicationProperties.setProperty(
+            BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
+
     Cache.saveProperties();
     Desktop.instance.doConfigureStructurePrefs();
     try
@@ -834,6 +986,30 @@ public class Preferences extends GPreferences
     }
   }
 
+  public void saveProxySettings()
+  {
+    String newProxyType = customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM
+            : noProxy.isSelected() ? Cache.PROXYTYPE_NONE
+                    : Cache.PROXYTYPE_SYSTEM;
+    Cache.applicationProperties.setProperty("USE_PROXY", newProxyType);
+    Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText());
+    Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText());
+    Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText());
+    Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText());
+    Cache.setOrRemove("PROXY_AUTH",
+            Boolean.toString(proxyAuth.isSelected()));
+    Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText());
+    Cache.proxyAuthPassword = proxyAuthPasswordPB.getPassword();
+    Cache.setProxyPropertiesFromPreferences(previousProxyType);
+    if (newProxyType.equals(Cache.PROXYTYPE_CUSTOM)
+            || !newProxyType.equals(previousProxyType))
+    {
+      // force a re-lookup of ws if proxytype is custom or has changed
+      wsPrefs.update++;
+    }
+    previousProxyType = newProxyType;
+  }
+
   /**
    * Do any necessary validation before saving settings. Return focus to the
    * first tab which fails validation.
@@ -853,7 +1029,7 @@ public class Preferences extends GPreferences
   @Override
   protected boolean validateStructure()
   {
-    return validateChimeraPath();
+    return validateViewerPath();
 
   }
 
@@ -897,7 +1073,7 @@ public class Preferences extends GPreferences
   {
     try
     {
-      if (!Jalview.isJS())
+      if (!Platform.isJS())
       {
         wsPrefs.updateWsMenuConfig(true);
         wsPrefs.refreshWs_actionPerformed(e);
@@ -1041,8 +1217,11 @@ public class Preferences extends GPreferences
   public void defaultBrowser_mouseClicked(MouseEvent e)
   {
     // TODO: JAL-3048 not needed for j2s
-    /*
-     * @j2sNative
+    if (!Platform.isJS()) // BH 2019
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
      */
     {
       JFileChooser chooser = new JFileChooser(".");
@@ -1135,7 +1314,7 @@ public class Preferences extends GPreferences
   {
     useLegacyGap.setSelected(false);
     useLegacyGaps_actionPerformed(null);
-    showHiddenAtStart.setSelected(true);
+    showHiddenAtStart.setSelected(false);
     hiddenColour.setBackground(
             jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
   }
@@ -1174,19 +1353,20 @@ public class Preferences extends GPreferences
   }
 
   /**
-   * Returns true if chimera path is to a valid executable, else show an error
-   * dialog.
+   * Returns true if structure viewer path is to a valid executable, else shows
+   * an error dialog. Does nothing if the path is empty, as is the case for Jmol
+   * (built in to Jalview) or when Jalview is left to try default paths.
    */
-  private boolean validateChimeraPath()
+  private boolean validateViewerPath()
   {
-    if (chimeraPath.getText().trim().length() > 0)
+    if (structureViewerPath.getText().trim().length() > 0)
     {
-      File f = new File(chimeraPath.getText());
+      File f = new File(structureViewerPath.getText());
       if (!f.canExecute())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                MessageManager.getString("label.invalid_chimera_path"),
-                MessageManager.getString("label.invalid_name"),
+                MessageManager.getString("label.invalid_viewer_path"),
+                MessageManager.getString("label.invalid_viewer_path"),
                 JvOptionPane.ERROR_MESSAGE);
         return false;
       }
@@ -1195,23 +1375,57 @@ public class Preferences extends GPreferences
   }
 
   /**
-   * If Chimera is selected, check it can be found on default or user-specified
-   * path, if not show a warning/help dialog.
+   * If Chimera or ChimeraX or Pymol is selected, check it can be found on
+   * default or user-specified path, if not show a warning/help dialog
    */
   @Override
   protected void structureViewer_actionPerformed(String selectedItem)
   {
-    if (!selectedItem.equals(ViewerType.CHIMERA.name()))
+    if (selectedItem.equals(ViewerType.JMOL.name()))
     {
+      structureViewerPath.setEnabled(false);
+      structureViewerPathLabel.setEnabled(false);
       return;
     }
     boolean found = false;
+    structureViewerPath.setEnabled(true);
+    structureViewerPathLabel.setEnabled(true);
+    structureViewerPathLabel.setText(MessageManager
+            .formatMessage("label.viewer_path", selectedItem));
 
     /*
-     * Try user-specified and standard paths for Chimera executable.
+     * Try user-specified and standard paths for structure viewer executable
      */
-    List<String> paths = StructureManager.getChimeraPaths();
-    paths.add(0, chimeraPath.getText());
+    String viewerPath = "";
+    List<String> paths = null;
+    try
+    {
+      ViewerType viewerType = ViewerType.valueOf(selectedItem);
+      switch (viewerType)
+      {
+      case JMOL:
+        // dealt with above
+        break;
+      case CHIMERA:
+        viewerPath = Cache.getDefault(CHIMERA_PATH, "");
+        paths = StructureManager.getChimeraPaths(false);
+        break;
+      case CHIMERAX:
+        viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
+        paths = StructureManager.getChimeraPaths(true);
+        break;
+      case PYMOL:
+        viewerPath = Cache.getDefault(PYMOL_PATH, "");
+        paths = PymolManager.getPymolPaths();
+        break;
+      }
+    } catch (IllegalArgumentException e)
+    {
+      // only valid entries should be in the drop-down
+    }
+    structureViewerPath.setText(viewerPath);
+
+    paths.add(0, structureViewerPath.getText());
     for (String path : paths)
     {
       if (new File(path.trim()).canExecute())
@@ -1220,12 +1434,13 @@ public class Preferences extends GPreferences
         break;
       }
     }
+
     if (!found)
     {
       String[] options = { "OK", "Help" };
       int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
               JvSwingUtils.wrapTooltip(true,
-                      MessageManager.getString("label.chimera_missing")),
+                      MessageManager.getString("label.viewer_missing")),
               "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
               null, options, options[0]);
       if (showHelp == JvOptionPane.NO_OPTION)