Merge branch 'alpha/JAL-3362_Jalview_212_alpha' into alpha/merge_212_JalviewJS_2112
[jalview.git] / src / jalview / gui / Preferences.java
index 3c0faab..f720e0a 100755 (executable)
@@ -24,6 +24,9 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.bin.Cache;
 import jalview.gui.Help.HelpId;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.hmmer.HmmerCommand;
+import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
 import jalview.io.FileFormatI;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
@@ -36,6 +39,7 @@ import jalview.urls.UrlLinkTableModel;
 import jalview.urls.api.UrlProviderFactoryI;
 import jalview.urls.api.UrlProviderI;
 import jalview.urls.desktop.DesktopUrlProviderFactory;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.util.UrlConstants;
@@ -48,16 +52,19 @@ import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.help.HelpSetException;
-import javax.swing.JColorChooser;
+import javax.swing.JComboBox;
 import javax.swing.JFileChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JPanel;
+import javax.swing.JTextField;
 import javax.swing.ListSelectionModel;
 import javax.swing.RowFilter;
 import javax.swing.RowSorter;
@@ -81,6 +88,15 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
  */
 public class Preferences extends GPreferences
 {
+  // suggested list delimiter character
+  public static final String COMMA = ",";
+
+  public static final String HMMSEARCH_SEQCOUNT = "HMMSEARCH_SEQCOUNT";
+
+  public static final String HMMINFO_GLOBAL_BACKGROUND = "HMMINFO_GLOBAL_BACKGROUND";
+
+  public static final String HMMALIGN_TRIM_TERMINI = "HMMALIGN_TRIM_TERMINI";
+
   public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
 
   public static final String SCALE_PROTEIN_TO_CDNA = "SCALE_PROTEIN_TO_CDNA";
@@ -102,6 +118,12 @@ public class Preferences extends GPreferences
   public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
 
   public static final String CHIMERA_PATH = "CHIMERA_PATH";
+  
+  public static final String HMMER_PATH = "HMMER_PATH";
+
+  public static final String CYGWIN_PATH = "CYGWIN_PATH";
+
+  public static final String HMMSEARCH_DBS = "HMMSEARCH_DBS";
 
   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
 
@@ -113,16 +135,13 @@ public class Preferences extends GPreferences
 
   public static final String USE_LEGACY_GAP = "USE_LEGACY_GAP";
 
-  private static final int MIN_FONT_SIZE = 1;
+  public static final String GAP_COLOUR = "GAP_COLOUR";
 
-  private static final int MAX_FONT_SIZE = 30;
+  public static final String HIDDEN_COLOUR = "HIDDEN_COLOUR";
 
-  private static final Color OVERVIEW_DEFAULT_GAP = Color.lightGray;
-
-  private static final Color OVERVIEW_DEFAULT_LEGACY_GAP = Color.white;
+  private static final int MIN_FONT_SIZE = 1;
 
-  private static final Color OVERVIEW_DEFAULT_HIDDEN = Color.darkGray
-          .darker();
+  private static final int MAX_FONT_SIZE = 30;
 
   /**
    * Holds name and link separated with | character. Sequence ID must be
@@ -171,8 +190,6 @@ public class Preferences extends GPreferences
 
   JInternalFrame frame;
 
-  DasSourceBrowser dasSource;
-
   private WsPreferences wsPrefs;
 
   private OptionsParam promptEachTimeOpt = new OptionsParam(
@@ -193,13 +210,18 @@ public class Preferences extends GPreferences
     super();
     frame = new JInternalFrame();
     frame.setContentPane(this);
-    dasSource = new DasSourceBrowser();
-    dasTab.add(dasSource, BorderLayout.CENTER);
-    wsPrefs = new WsPreferences();
-    wsTab.add(wsPrefs, BorderLayout.CENTER);
+    if (!Platform.isJS())
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
+     */
+    {
+      wsPrefs = new WsPreferences();
+      wsTab.add(wsPrefs, BorderLayout.CENTER);
+    }
     int width = 500, height = 450;
-    new jalview.util.Platform();
-    if (Platform.isAMac())
+    if (Platform.isAMacAndNotJS())
     {
       width = 570;
       height = 480;
@@ -210,6 +232,63 @@ public class Preferences extends GPreferences
     frame.setMinimumSize(new Dimension(width, height));
 
     /*
+     * Set HMMER tab defaults
+     */
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
+    {
+      hmmerBackgroundUniprot.setSelected(true);
+    }
+    else
+    {
+      hmmerBackgroundAlignment.setSelected(true);
+    }
+    hmmerSequenceCount
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
+    hmmerPath.setText(Cache.getProperty(HMMER_PATH));
+    hmmerPath.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        validateHmmerPath();
+      }
+    });
+    hmmerPath.addFocusListener(new FocusAdapter()
+    {
+      @Override
+      public void focusLost(FocusEvent e)
+      {
+        validateHmmerPath();
+      }
+    });
+    if (cygwinPath != null)
+    {
+      String path = Cache.getProperty(CYGWIN_PATH);
+      if (path == null)
+      {
+        path = FileUtils.getPathTo("bash");
+      }
+      cygwinPath.setText(path);
+      cygwinPath.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+      cygwinPath.addFocusListener(new FocusAdapter()
+      {
+        @Override
+        public void focusLost(FocusEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+    }
+
+    /*
      * Set Visual tab defaults
      */
     seqLimit.setSelected(Cache.getDefault("SHOW_JVSUFFIX", true));
@@ -232,6 +311,9 @@ public class Preferences extends GPreferences
             Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
     showConsensLogo
             .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
+    showInformationHistogram.setSelected(
+            Cache.getDefault("SHOW_INFORMATION_HISTOGRAM", true));
+    showHMMLogo.setSelected(Cache.getDefault("SHOW_HMM_LOGO", false));
     showNpTooltip
             .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
     showDbRefTooltip
@@ -258,7 +340,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));
 
@@ -323,15 +405,16 @@ public class Preferences extends GPreferences
      * Set overview panel defaults
      */
     gapColour.setBackground(
-            Cache.getDefaultColour("GAP_COLOUR", OVERVIEW_DEFAULT_GAP));
+            Cache.getDefaultColour(GAP_COLOUR,
+                    jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP));
     hiddenColour.setBackground(
-            Cache.getDefaultColour("HIDDEN_COLOUR",
-                    OVERVIEW_DEFAULT_HIDDEN));
-    useLegacyGap.setSelected(Cache.getDefault("USE_LEGACY_GAP", false));
+            Cache.getDefaultColour(HIDDEN_COLOUR,
+                    jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN));
+    useLegacyGap.setSelected(Cache.getDefault(USE_LEGACY_GAP, false));
     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.
@@ -388,7 +471,8 @@ public class Preferences extends GPreferences
             new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING));
 
     sorter.setSortKeys(sortKeys);
-    sorter.sort();
+    // BH 2018 setSortKeys will do the sort
+    // sorter.sort();
 
     // set up filtering
     ActionListener onReset;
@@ -507,28 +591,16 @@ public class Preferences extends GPreferences
     /*
      * Set Output tab defaults
      */
-    epsRendering.addItem(promptEachTimeOpt);
-    epsRendering.addItem(lineArtOpt);
-    epsRendering.addItem(textOpt);
-    String defaultEPS = Cache.getDefault("EPS_RENDERING",
-            "Prompt each time");
-    if (defaultEPS.equalsIgnoreCase("Text"))
-    {
-      epsRendering.setSelectedItem(textOpt);
-    }
-    else if (defaultEPS.equalsIgnoreCase("Lineart"))
-    {
-      epsRendering.setSelectedItem(lineArtOpt);
-    }
-    else
-    {
-      epsRendering.setSelectedItem(promptEachTimeOpt);
-    }
+    setupOutputCombo(epsRendering, "EPS_RENDERING");
+    setupOutputCombo(htmlRendering, "HTML_RENDERING");
+    setupOutputCombo(svgRendering, "SVG_RENDERING");
     autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false));
     userIdWidth.setEnabled(!autoIdWidth.isSelected());
     userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
-    Integer wi = Cache.getIntegerProperty("FIGURE_USERIDWIDTH");
+    Integer wi = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH");
     userIdWidth.setText(wi == null ? "" : wi.toString());
+    // TODO: refactor to use common enum via FormatAdapter and allow extension
+    // for new flat file formats
     blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
     clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
     fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
@@ -550,6 +622,45 @@ public class Preferences extends GPreferences
 
     annotations_actionPerformed(null); // update the display of the annotation
                                        // settings
+    
+    
+    /*
+     * Set Backups tab defaults
+     */
+    loadLastSavedBackupsOptions();
+  }
+
+  /**
+   * A helper method that sets the items and initial selection in a character
+   * rendering option list (Prompt each time/Lineart/Text)
+   * 
+   * @param comboBox
+   * @param propertyKey
+   */
+  protected void setupOutputCombo(JComboBox<Object> comboBox,
+          String propertyKey)
+  {
+    comboBox.addItem(promptEachTimeOpt);
+    comboBox.addItem(lineArtOpt);
+    comboBox.addItem(textOpt);
+    
+    /*
+     * JalviewJS doesn't support Lineart so force it to Text
+     */
+    String defaultOption = Platform.isJS() ? "Text"
+            : Cache.getDefault(propertyKey, "Prompt each time");
+    if (defaultOption.equalsIgnoreCase("Text"))
+    {
+      comboBox.setSelectedItem(textOpt);
+    }
+    else if (defaultOption.equalsIgnoreCase("Lineart"))
+    {
+      comboBox.setSelectedItem(lineArtOpt);
+    }
+    else
+    {
+      comboBox.setSelectedItem(promptEachTimeOpt);
+    }
   }
 
   /**
@@ -610,6 +721,10 @@ public class Preferences extends GPreferences
             Boolean.toString(showConsensHistogram.isSelected()));
     Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
             Boolean.toString(showConsensLogo.isSelected()));
+    Cache.applicationProperties.setProperty("SHOW_INFORMATION_HISTOGRAM",
+            Boolean.toString(showConsensHistogram.isSelected()));
+    Cache.applicationProperties.setProperty("SHOW_HMM_LOGO",
+            Boolean.toString(showHMMLogo.isSelected()));
     Cache.applicationProperties.setProperty("ANTI_ALIAS",
             Boolean.toString(smoothFont.isSelected()));
     Cache.applicationProperties.setProperty(SCALE_PROTEIN_TO_CDNA,
@@ -656,10 +771,46 @@ public class Preferences extends GPreferences
             maxColour.getBackground());
 
     /*
+     * Save HMMER settings
+     */
+    Cache.applicationProperties.setProperty(HMMALIGN_TRIM_TERMINI,
+            Boolean.toString(hmmrTrimTermini.isSelected()));
+    Cache.applicationProperties.setProperty(HMMINFO_GLOBAL_BACKGROUND,
+            Boolean.toString(hmmerBackgroundUniprot.isSelected()));
+    Cache.applicationProperties.setProperty(HMMSEARCH_SEQCOUNT,
+            hmmerSequenceCount.getText());
+    Cache.setOrRemove(HMMER_PATH, hmmerPath.getText());
+    if (cygwinPath != null)
+    {
+      Cache.setOrRemove(CYGWIN_PATH, cygwinPath.getText());
+    }
+    AlignFrame[] frames = Desktop.getAlignFrames();
+    if (frames != null && frames.length > 0)
+    {
+      for (AlignFrame f : frames)
+      {
+        f.updateHMMERStatus();
+      }
+    }
+    
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
+    {
+      hmmerBackgroundUniprot.setSelected(true);
+    }
+    else
+    {
+      hmmerBackgroundAlignment.setSelected(true);
+    }
+    hmmerSequenceCount
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
+    hmmerPath.setText(Cache.getProperty(HMMER_PATH));
+
+    /*
      * Save Overview settings
      */
-    Cache.setColourProperty("GAP_COLOUR", gapColour.getBackground());
-    Cache.setColourProperty("HIDDEN_COLOUR", hiddenColour.getBackground());
+    Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
+    Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
     Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
             Boolean.toString(useLegacyGap.isSelected()));
     Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
@@ -688,6 +839,10 @@ public class Preferences extends GPreferences
      */
     Cache.applicationProperties.setProperty("EPS_RENDERING",
             ((OptionsParam) epsRendering.getSelectedItem()).getCode());
+    Cache.applicationProperties.setProperty("HTML_RENDERING",
+            ((OptionsParam) htmlRendering.getSelectedItem()).getCode());
+    Cache.applicationProperties.setProperty("SVG_RENDERING",
+            ((OptionsParam) svgRendering.getSelectedItem()).getCode());
 
     /*
      * Save Connections settings
@@ -784,7 +939,7 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("FIGURE_AUTOIDWIDTH",
             Boolean.toString(autoIdWidth.isSelected()));
     userIdWidth_actionPerformed();
-    Cache.applicationProperties.setProperty("FIGURE_USERIDWIDTH",
+    Cache.applicationProperties.setProperty("FIGURE_FIXEDIDWIDTH",
             userIdWidth.getText());
 
     /*
@@ -797,8 +952,34 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("PAD_GAPS",
             Boolean.toString(padGaps.isSelected()));
 
-    dasSource.saveProperties(Cache.applicationProperties);
-    wsPrefs.updateAndRefreshWsMenuConfig(false);
+    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
@@ -838,6 +1019,7 @@ public class Preferences extends GPreferences
   @Override
   public void startupFileTextfield_mouseClicked()
   {
+    // TODO: JAL-3048 not needed for Jalview-JS
     String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
     JalviewFileChooser chooser = JalviewFileChooser
             .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
@@ -871,8 +1053,11 @@ public class Preferences extends GPreferences
   {
     try
     {
-      wsPrefs.updateWsMenuConfig(true);
-      wsPrefs.refreshWs_actionPerformed(e);
+      if (!Platform.isJS())
+      {
+        wsPrefs.updateWsMenuConfig(true);
+        wsPrefs.refreshWs_actionPerformed(e);
+      }
       frame.setClosed(true);
     } catch (Exception ex)
     {
@@ -898,6 +1083,8 @@ public class Preferences extends GPreferences
             && (identity.isSelected() || showGroupConsensus.isSelected()));
     showConsensLogo.setEnabled(annotations.isSelected()
             && (identity.isSelected() || showGroupConsensus.isSelected()));
+    showInformationHistogram.setEnabled(annotations.isSelected());
+    showHMMLogo.setEnabled(annotations.isSelected());
   }
 
   @Override
@@ -1011,17 +1198,25 @@ public class Preferences extends GPreferences
   @Override
   public void defaultBrowser_mouseClicked(MouseEvent e)
   {
-    JFileChooser chooser = new JFileChooser(".");
-    chooser.setDialogTitle(
-            MessageManager.getString("label.select_default_browser"));
+    // TODO: JAL-3048 not needed for j2s
+    if (!Platform.isJS()) // BH 2019
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
+     */
+    {
+      JFileChooser chooser = new JFileChooser(".");
+      chooser.setDialogTitle(
+              MessageManager.getString("label.select_default_browser"));
 
-    int value = chooser.showOpenDialog(this);
+      int value = chooser.showOpenDialog(this);
 
-    if (value == JFileChooser.APPROVE_OPTION)
-    {
-      defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath());
+      if (value == JFileChooser.APPROVE_OPTION)
+      {
+        defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath());
+      }
     }
-
   }
 
   /*
@@ -1046,27 +1241,17 @@ public class Preferences extends GPreferences
   @Override
   public void minColour_actionPerformed(JPanel panel)
   {
-    Color col = JColorChooser.showDialog(this,
+    JalviewColourChooser.showColourChooser(this,
             MessageManager.getString("label.select_colour_minimum_value"),
-            minColour.getBackground());
-    if (col != null)
-    {
-      panel.setBackground(col);
-    }
-    panel.repaint();
+            panel);
   }
 
   @Override
   public void maxColour_actionPerformed(JPanel panel)
   {
-    Color col = JColorChooser.showDialog(this,
+    JalviewColourChooser.showColourChooser(this,
             MessageManager.getString("label.select_colour_maximum_value"),
-            maxColour.getBackground());
-    if (col != null)
-    {
-      panel.setBackground(col);
-    }
-    panel.repaint();
+            panel);
   }
 
   @Override
@@ -1074,28 +1259,18 @@ public class Preferences extends GPreferences
   {
     if (!useLegacyGap.isSelected())
     {
-      Color col = JColorChooser.showDialog(this,
+      JalviewColourChooser.showColourChooser(this,
               MessageManager.getString("label.select_gap_colour"),
-              gapColour.getBackground());
-      if (col != null)
-      {
-        gap.setBackground(col);
-      }
-      gap.repaint();
+              gap);
     }
   }
 
   @Override
   public void hiddenColour_actionPerformed(JPanel hidden)
   {
-    Color col = JColorChooser.showDialog(this,
+    JalviewColourChooser.showColourChooser(this,
             MessageManager.getString("label.select_hidden_colour"),
-            hiddenColour.getBackground());
-    if (col != null)
-    {
-      hidden.setBackground(col);
-    }
-    hidden.repaint();
+            hidden);
   }
 
   @Override
@@ -1104,11 +1279,13 @@ public class Preferences extends GPreferences
     boolean enabled = useLegacyGap.isSelected();
     if (enabled)
     {
-      gapColour.setBackground(OVERVIEW_DEFAULT_LEGACY_GAP);
+      gapColour.setBackground(
+              jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
     }
     else
     {
-      gapColour.setBackground(OVERVIEW_DEFAULT_GAP);
+      gapColour.setBackground(
+              jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
     }
     gapColour.setEnabled(!enabled);
     gapLabel.setEnabled(!enabled);
@@ -1119,8 +1296,9 @@ public class Preferences extends GPreferences
   {
     useLegacyGap.setSelected(false);
     useLegacyGaps_actionPerformed(null);
-    showHiddenAtStart.setSelected(true);
-    hiddenColour.setBackground(OVERVIEW_DEFAULT_HIDDEN);
+    showHiddenAtStart.setSelected(false);
+    hiddenColour.setBackground(
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
   }
 
   @Override
@@ -1140,12 +1318,12 @@ public class Preferences extends GPreferences
       }
     } catch (NumberFormatException x)
     {
+      userIdWidth.setText("");
       JvOptionPane.showInternalMessageDialog(Desktop.desktop,
               MessageManager
                       .getString("warn.user_defined_width_requirements"),
               MessageManager.getString("label.invalid_id_column_width"),
               JvOptionPane.WARNING_MESSAGE);
-      userIdWidth.setText("");
     }
   }
 
@@ -1176,6 +1354,57 @@ public class Preferences extends GPreferences
     }
     return true;
   }
+  
+  /**
+   * Returns true if the given text field contains a path to a folder that
+   * contains an executable with the given name, else false (after showing a
+   * warning dialog). The executable name will be tried with .exe appended if not
+   * found.
+   * 
+   * @param textField
+   * @param executable
+   */
+  protected boolean validateExecutablePath(JTextField textField, String executable)
+  {
+    String folder = textField.getText().trim();
+
+    if (FileUtils.getExecutable(executable, folder) != null)
+    {
+      return true;
+    }
+    if (folder.length() > 0)
+    {
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage("label.executable_not_found",
+                      executable),
+              MessageManager.getString("label.invalid_folder"),
+              JvOptionPane.ERROR_MESSAGE);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if a file can be executed
+   * 
+   * @param path
+   *          the path to the file
+   * @return
+   */
+  public boolean canExecute(String path)
+  {
+    File file = new File(path);
+    if (!file.canExecute())
+    {
+      file = new File(path + ".exe");
+      {
+        if (!file.canExecute())
+        {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
 
   /**
    * If Chimera is selected, check it can be found on default or user-specified
@@ -1224,6 +1453,18 @@ public class Preferences extends GPreferences
     }
   }
 
+  @Override
+  protected void validateHmmerPath()
+  {
+    validateExecutablePath(hmmerPath, HmmerCommand.HMMBUILD);
+  }
+
+  @Override
+  protected void validateCygwinPath()
+  {
+    validateExecutablePath(cygwinPath, "run");
+  }
+
   public class OptionsParam
   {
     private String name;