JAL-2077 - reinstate popups on osx
[jalview.git] / src / jalview / gui / FeatureSettings.java
index 2190858..6633156 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  */
 package jalview.gui;
 
-import jalview.analysis.AlignmentSorter;
+import jalview.api.FeatureSettingsControllerI;
 import jalview.bin.Cache;
-import jalview.commands.OrderCommand;
-import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.Help.HelpId;
 import jalview.io.JalviewFileChooser;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.GraduatedColor;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.dbsources.das.api.jalviewSourceI;
 
 import java.awt.BorderLayout;
@@ -55,12 +54,15 @@ import java.io.FileOutputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.Vector;
 
+import javax.help.HelpSetException;
 import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
 import javax.swing.Icon;
@@ -89,7 +91,8 @@ import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 
-public class FeatureSettings extends JPanel
+public class FeatureSettings extends JPanel implements
+        FeatureSettingsControllerI
 {
   DasSourceBrowser dassourceBrowser;
 
@@ -105,6 +108,8 @@ public class FeatureSettings extends JPanel
 
   Object[][] originalData;
 
+  private float originalTransparency;
+
   final JInternalFrame frame;
 
   JScrollPane scrollPane = new JScrollPane();
@@ -121,8 +126,9 @@ public class FeatureSettings extends JPanel
   {
     this.af = af;
     fr = af.getFeatureRenderer();
-
-    transparency.setMaximum(100 - (int) (fr.transparency * 100));
+    // allow transparency to be recovered
+    transparency.setMaximum(100 - (int) ((originalTransparency = fr
+            .getTransparency()) * 100));
 
     try
     {
@@ -132,7 +138,22 @@ public class FeatureSettings extends JPanel
       ex.printStackTrace();
     }
 
-    table = new JTable();
+    table = new JTable()
+    {
+      @Override
+      public String getToolTipText(MouseEvent e)
+      {
+        if (table.columnAtPoint(e.getPoint()) == 0)
+        {
+          /*
+           * Tooltip for feature name only
+           */
+          return JvSwingUtils.wrapTooltip(true, MessageManager
+                  .getString("label.feature_settings_click_drag"));
+        }
+        return null;
+      }
+    };
     table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
     table.setFont(new Font("Verdana", Font.PLAIN, 12));
     table.setDefaultRenderer(Color.class, new ColorRenderer());
@@ -145,14 +166,15 @@ public class FeatureSettings extends JPanel
 
     table.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent evt)
       {
         selectedRow = table.rowAtPoint(evt.getPoint());
-        if (SwingUtilities.isRightMouseButton(evt))
+        if (evt.isPopupTrigger())
         {
           popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
-                  table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
-                  evt.getY());
+                  table.getValueAt(selectedRow, 1), fr.getMinMax(),
+                  evt.getX(), evt.getY());
         }
         else if (evt.getClickCount() == 2)
         {
@@ -171,54 +193,49 @@ public class FeatureSettings extends JPanel
         if (evt.isPopupTrigger())
         {
           popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
-                  table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
-                  evt.getY());
+                  table.getValueAt(selectedRow, 1), fr.getMinMax(),
+                  evt.getX(), evt.getY());
         }
       }
     });
 
     table.addMouseMotionListener(new MouseMotionAdapter()
     {
+      @Override
       public void mouseDragged(MouseEvent evt)
       {
         int newRow = table.rowAtPoint(evt.getPoint());
         if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
         {
-          Object[] temp = new Object[3];
-          temp[0] = table.getValueAt(selectedRow, 0);
-          temp[1] = table.getValueAt(selectedRow, 1);
-          temp[2] = table.getValueAt(selectedRow, 2);
-
-          table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
-          table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
-          table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
-
-          table.setValueAt(temp[0], newRow, 0);
-          table.setValueAt(temp[1], newRow, 1);
-          table.setValueAt(temp[2], newRow, 2);
-
+          Object[][] data = ((FeatureTableModel) table.getModel())
+                  .getData();
+          Object[] temp = data[selectedRow];
+          data[selectedRow] = data[newRow];
+          data[newRow] = temp;
+          updateFeatureRenderer(data);
+          table.repaint();
           selectedRow = newRow;
         }
       }
     });
-    table.setToolTipText(JvSwingUtils
-                    .wrapTooltip(true, MessageManager.getString("label.feature_settings_click_drag")));
+    // table.setToolTipText(JvSwingUtils.wrapTooltip(true,
+    // MessageManager.getString("label.feature_settings_click_drag")));
     scrollPane.setViewportView(table);
 
     dassourceBrowser = new DasSourceBrowser(this);
     dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
 
-    if (af.getViewport().getFeaturesDisplayed() == null
-            || fr.renderOrder == null)
+    if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
     {
       fr.findAllFeatures(true); // display everything!
     }
 
-    setTableData();
+    discoverAllFeatureData();
     final PropertyChangeListener change;
     final FeatureSettings fs = this;
     fr.addPropertyChangeListener(change = new PropertyChangeListener()
     {
+      @Override
       public void propertyChange(PropertyChangeEvent evt)
       {
         if (!fs.resettingTable && !fs.handlingUpdate)
@@ -249,6 +266,7 @@ public class FeatureSettings extends JPanel
 
     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
     {
+      @Override
       public void internalFrameClosed(
               javax.swing.event.InternalFrameEvent evt)
       {
@@ -260,11 +278,11 @@ public class FeatureSettings extends JPanel
   }
 
   protected void popupSort(final int selectedRow, final String type,
-          final Object typeCol, final Hashtable minmax, int x, int y)
+          final Object typeCol, final Map<String, float[][]> minmax, int x,
+          int y)
   {
     JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
-            "label.settings_for_param", new String[]
-            { type }));
+            "label.settings_for_param", new String[] { type }));
     JMenuItem scr = new JMenuItem(
             MessageManager.getString("label.sort_by_score"));
     men.add(scr);
@@ -272,10 +290,11 @@ public class FeatureSettings extends JPanel
     scr.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByScore(new String[]
-        { type });
+        me.af.avc.sortAlignmentByFeatureScore(Arrays
+                .asList(new String[] { type }));
       }
 
     });
@@ -284,17 +303,18 @@ public class FeatureSettings extends JPanel
     dens.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByDens(new String[]
-        { type });
+        me.af.avc.sortAlignmentByFeatureDensity(Arrays
+                .asList(new String[] { type }));
       }
 
     });
     men.add(dens);
     if (minmax != null)
     {
-      final Object typeMinMax = minmax.get(type);
+      final float[][] typeMinMax = minmax.get(type);
       /*
        * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
        * this is broken at the moment and isn't that useful anyway!
@@ -309,7 +329,7 @@ public class FeatureSettings extends JPanel
        * 
        * men.add(chb);
        */
-      if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+      if (typeMinMax != null && typeMinMax[0] != null)
       {
         // if (table.getValueAt(row, column));
         // graduated colourschemes for those where minmax exists for the
@@ -322,6 +342,7 @@ public class FeatureSettings extends JPanel
         {
           JColorChooser colorChooser;
 
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             if (e.getSource() == mxcol)
@@ -408,27 +429,22 @@ public class FeatureSettings extends JPanel
    */
   Hashtable typeWidth = null;
 
-  synchronized public void setTableData()
+  @Override
+  synchronized public void discoverAllFeatureData()
   {
-    if (fr.featureGroups == null)
-    {
-      fr.featureGroups = new Hashtable();
-    }
     Vector allFeatures = new Vector();
     Vector allGroups = new Vector();
     SequenceFeature[] tmpfeatures;
     String group;
     for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
     {
-      if (af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures() == null)
+      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
+              .getSequenceFeatures();
+      if (tmpfeatures == null)
       {
         continue;
       }
 
-      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures();
-
       int index = 0;
       while (index < tmpfeatures.length)
       {
@@ -444,10 +460,7 @@ public class FeatureSettings extends JPanel
           if (!allGroups.contains(group))
           {
             allGroups.addElement(group);
-            if (group != null)
-            {
-              checkGroupState(group);
-            }
+            checkGroupState(group);
           }
         }
 
@@ -465,21 +478,14 @@ public class FeatureSettings extends JPanel
   }
 
   /**
+   * Synchronise gui group list and check visibility of group
    * 
    * @param group
-   * @return true if group has been seen before and is already added to set.
+   * @return true if group is visible
    */
   private boolean checkGroupState(String group)
   {
-    boolean visible;
-    if (fr.featureGroups.containsKey(group))
-    {
-      visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
-    }
-    else
-    {
-      visible = true; // new group is always made visible
-    }
+    boolean visible = fr.checkGroupVisibility(group, true);
 
     if (groupPanel == null)
     {
@@ -500,31 +506,28 @@ public class FeatureSettings extends JPanel
     if (alreadyAdded)
     {
 
-      return true;
+      return visible;
     }
-
-    fr.featureGroups.put(group, new Boolean(visible));
     final String grp = group;
     final JCheckBox check = new JCheckBox(group, visible);
     check.setFont(new Font("Serif", Font.BOLD, 12));
     check.addItemListener(new ItemListener()
     {
+      @Override
       public void itemStateChanged(ItemEvent evt)
       {
-        fr.featureGroups.put(check.getText(),
-                new Boolean(check.isSelected()));
-        af.alignPanel.seqPanel.seqCanvas.repaint();
+        fr.setGroupVisibility(check.getText(), check.isSelected());
+        af.alignPanel.getSeqPanel().seqCanvas.repaint();
         if (af.alignPanel.overviewPanel != null)
         {
           af.alignPanel.overviewPanel.updateOverviewImage();
         }
 
-        resetTable(new String[]
-        { grp });
+        resetTable(new String[] { grp });
       }
     });
     groupPanel.add(check);
-    return false;
+    return visible;
   }
 
   boolean resettingTable = false;
@@ -551,7 +554,7 @@ public class FeatureSettings extends JPanel
     {
 
       tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures();
+              .getSequenceFeatures();
       if (tmpfeatures == null)
       {
         continue;
@@ -568,11 +571,8 @@ public class FeatureSettings extends JPanel
           continue;
         }
 
-        if (group == null || fr.featureGroups.get(group) == null
-                || ((Boolean) fr.featureGroups.get(group)).booleanValue())
+        if (group == null || checkGroupState(group))
         {
-          if (group != null)
-            checkGroupState(group);
           type = tmpfeatures[index].getType();
           if (!visibleChecks.contains(type))
           {
@@ -607,17 +607,20 @@ public class FeatureSettings extends JPanel
     Object[][] data = new Object[fSize][3];
     int dataIndex = 0;
 
-    if (fr.renderOrder != null)
+    if (fr.hasRenderOrder())
     {
       if (!handlingUpdate)
+      {
         fr.findAllFeatures(groupChanged != null); // prod to update
-      // colourschemes. but don't
-      // affect display
-      // First add the checks in the previous render order,
-      // in case the window has been closed and reopened
-      for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
+        // colourschemes. but don't
+        // affect display
+        // First add the checks in the previous render order,
+        // in case the window has been closed and reopened
+      }
+      List<String> frl = fr.getRenderOrder();
+      for (int ro = frl.size() - 1; ro > -1; ro--)
       {
-        type = fr.renderOrder[ro];
+        type = frl.get(ro);
 
         if (!visibleChecks.contains(type))
         {
@@ -626,8 +629,8 @@ public class FeatureSettings extends JPanel
 
         data[dataIndex][0] = type;
         data[dataIndex][1] = fr.getFeatureStyle(type);
-        data[dataIndex][2] = new Boolean(
-                af.getViewport().getFeaturesDisplayed().containsKey(type));
+        data[dataIndex][2] = new Boolean(af.getViewport()
+                .getFeaturesDisplayed().isVisible(type));
         dataIndex++;
         visibleChecks.removeElement(type);
       }
@@ -645,7 +648,7 @@ public class FeatureSettings extends JPanel
       if (data[dataIndex][1] == null)
       {
         // "Colour has been updated in another view!!"
-        fr.renderOrder = null;
+        fr.clearRenderOrder();
         return;
       }
 
@@ -667,8 +670,8 @@ public class FeatureSettings extends JPanel
 
     if (groupPanel != null)
     {
-      groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
-              4));
+      groupPanel.setLayout(new GridLayout(
+              fr.getFeatureGroupsSize() / 4 + 1, 4));
 
       groupPanel.validate();
       bigPanel.add(groupPanel, BorderLayout.NORTH);
@@ -691,22 +694,30 @@ public class FeatureSettings extends JPanel
     {
       order[i] = fr.getOrder(data[i][0].toString());
       if (order[i] < 0)
+      {
         order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
+      }
       if (i > 1)
+      {
         sort = sort || order[i - 1] > order[i];
+      }
     }
     if (sort)
+    {
       jalview.util.QuickSort.sort(order, data);
+    }
   }
 
   void load()
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
-            { "fc" }, new String[]
-            { "Sequence Feature Colours" }, "Sequence Feature Colours");
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
+            new String[] { "fc" },
+            new String[] { "Sequence Feature Colours" },
+            "Sequence Feature Colours");
     chooser.setFileView(new jalview.io.JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.load_feature_colours"));
+    chooser.setDialogTitle(MessageManager
+            .getString("label.load_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.load"));
 
     int value = chooser.showOpenDialog(this);
@@ -721,8 +732,7 @@ public class FeatureSettings extends JPanel
                 file), "UTF-8");
 
         jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-        jucs = jucs
-                .unmarshal(in);
+        jucs = jucs.unmarshal(in);
 
         for (int i = jucs.getColourCount() - 1; i >= 0; i--)
         {
@@ -800,11 +810,13 @@ public class FeatureSettings extends JPanel
   void save()
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
-            { "fc" }, new String[]
-            { "Sequence Feature Colours" }, "Sequence Feature Colours");
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
+            new String[] { "fc" },
+            new String[] { "Sequence Feature Colours" },
+            "Sequence Feature Colours");
     chooser.setFileView(new jalview.io.JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_feature_colours"));
+    chooser.setDialogTitle(MessageManager
+            .getString("label.save_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -819,9 +831,10 @@ public class FeatureSettings extends JPanel
         PrintWriter out = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream(choice), "UTF-8"));
 
-        Iterator e = fr.featureColours.keySet().iterator();
-        float[] sortOrder = new float[fr.featureColours.size()];
-        String[] sortTypes = new String[fr.featureColours.size()];
+        Set fr_colours = fr.getAllFeatureColours();
+        Iterator e = fr_colours.iterator();
+        float[] sortOrder = new float[fr_colours.size()];
+        String[] sortTypes = new String[fr_colours.size()];
         int i = 0;
         while (e.hasNext())
         {
@@ -887,7 +900,9 @@ public class FeatureSettings extends JPanel
   public void orderByAvWidth()
   {
     if (table == null || table.getModel() == null)
+    {
       return;
+    }
     Object[][] data = ((FeatureTableModel) table.getModel()).getData();
     float[] width = new float[data.length];
     float[] awidth;
@@ -909,7 +924,9 @@ public class FeatureSettings extends JPanel
         width[i] = 0;
       }
       if (max < width[i])
+      {
         max = width[i];
+      }
     }
     boolean sort = false;
     for (int i = 0; i < width.length; i++)
@@ -929,11 +946,15 @@ public class FeatureSettings extends JPanel
         fr.setOrder(data[i][0].toString(), width[i]); // store for later
       }
       if (i > 0)
+      {
         sort = sort || width[i - 1] > width[i];
+      }
     }
     if (sort)
+    {
       jalview.util.QuickSort.sort(width, data);
-    // update global priority order
+      // update global priority order
+    }
 
     updateFeatureRenderer(data, false);
     table.repaint();
@@ -955,10 +976,19 @@ public class FeatureSettings extends JPanel
     updateFeatureRenderer(data, true);
   }
 
+  /**
+   * Update the priority order of features; only repaint if this changed the
+   * order of visible features
+   * 
+   * @param data
+   * @param visibleNew
+   */
   private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
   {
-    fr.setFeaturePriority(data, visibleNew);
-    af.alignPanel.paintAlignment(true);
+    if (fr.setFeaturePriority(data, visibleNew))
+    {
+      af.alignPanel.paintAlignment(true);
+    }
   }
 
   int selectedRow = -1;
@@ -1001,7 +1031,9 @@ public class FeatureSettings extends JPanel
 
   JButton sortByDens = new JButton();
 
-  JPanel transbuttons = new JPanel(new GridLayout(4, 1));
+  JButton help = new JButton();
+
+  JPanel transbuttons = new JPanel(new GridLayout(5, 1));
 
   private void jbInit() throws Exception
   {
@@ -1013,6 +1045,7 @@ public class FeatureSettings extends JPanel
     invert.setText(MessageManager.getString("label.invert_selection"));
     invert.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         invertSelection();
@@ -1022,6 +1055,7 @@ public class FeatureSettings extends JPanel
     optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
     optimizeOrder.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         orderByAvWidth();
@@ -1032,9 +1066,10 @@ public class FeatureSettings extends JPanel
             .setText(MessageManager.getString("label.seq_sort_by_score"));
     sortByScore.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        sortByScore(null);
+        af.avc.sortAlignmentByFeatureScore(null);
       }
     });
     sortByDens.setFont(JvSwingUtils.getLabelFont());
@@ -1042,17 +1077,52 @@ public class FeatureSettings extends JPanel
             .getString("label.sequence_sort_by_density"));
     sortByDens.addActionListener(new ActionListener()
     {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        af.avc.sortAlignmentByFeatureDensity(null);
+      }
+    });
+    help.setFont(JvSwingUtils.getLabelFont());
+    help.setText(MessageManager.getString("action.help"));
+    help.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        try
+        {
+          Help.showHelpWindow(HelpId.SequenceFeatureSettings);
+        } catch (HelpSetException e1)
+        {
+          e1.printStackTrace();
+        }
+      }
+    });
+    help.setFont(JvSwingUtils.getLabelFont());
+    help.setText(MessageManager.getString("action.help"));
+    help.addActionListener(new ActionListener()
+    {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        sortByDens(null);
+        try
+        {
+          Help.showHelpWindow(HelpId.SequenceFeatureSettings);
+        } catch (HelpSetException e1)
+        {
+          e1.printStackTrace();
+        }
       }
     });
     cancel.setFont(JvSwingUtils.getLabelFont());
     cancel.setText(MessageManager.getString("action.cancel"));
     cancel.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
+        fr.setTransparency(originalTransparency);
         updateFeatureRenderer(originalData);
         close();
       }
@@ -1061,6 +1131,7 @@ public class FeatureSettings extends JPanel
     ok.setText(MessageManager.getString("action.ok"));
     ok.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         close();
@@ -1070,6 +1141,7 @@ public class FeatureSettings extends JPanel
     loadColours.setText(MessageManager.getString("label.load_colours"));
     loadColours.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         load();
@@ -1079,6 +1151,7 @@ public class FeatureSettings extends JPanel
     saveColours.setText(MessageManager.getString("label.save_colours"));
     saveColours.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         save();
@@ -1086,6 +1159,7 @@ public class FeatureSettings extends JPanel
     });
     transparency.addChangeListener(new ChangeListener()
     {
+      @Override
       public void stateChanged(ChangeEvent evt)
       {
         fr.setTransparency((100 - transparency.getValue()) / 100f);
@@ -1094,9 +1168,12 @@ public class FeatureSettings extends JPanel
     });
 
     transparency.setMaximum(70);
+    transparency.setToolTipText(MessageManager
+            .getString("label.transparency_tip"));
     fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
     fetchDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         fetchDAS_actionPerformed(e);
@@ -1105,6 +1182,7 @@ public class FeatureSettings extends JPanel
     saveDAS.setText(MessageManager.getString("action.save_as_default"));
     saveDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         saveDAS_actionPerformed(e);
@@ -1116,19 +1194,25 @@ public class FeatureSettings extends JPanel
     cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
     cancelDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cancelDAS_actionPerformed(e);
       }
     });
     this.add(tabbedPane, java.awt.BorderLayout.CENTER);
-    tabbedPane.addTab(MessageManager.getString("label.feature_settings"), settingsPane);
-    tabbedPane.addTab(MessageManager.getString("label.das_settings"), dasSettingsPane);
+    tabbedPane.addTab(MessageManager.getString("label.feature_settings"),
+            settingsPane);
+    tabbedPane.addTab(MessageManager.getString("label.das_settings"),
+            dasSettingsPane);
     bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
     transbuttons.add(optimizeOrder);
     transbuttons.add(invert);
     transbuttons.add(sortByScore);
     transbuttons.add(sortByDens);
+    transbuttons.add(help);
+    JPanel sliderPanel = new JPanel();
+    sliderPanel.add(transparency);
     transPanel.add(transparency);
     transPanel.add(transbuttons);
     buttonPanel.add(ok);
@@ -1144,131 +1228,6 @@ public class FeatureSettings extends JPanel
     settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
   }
 
-  protected void sortByDens(String[] typ)
-  {
-    sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
-  }
-
-  protected void sortBy(String[] typ, String methodText, final String method)
-  {
-    if (typ == null)
-    {
-      typ = getDisplayedFeatureTypes();
-    }
-    String gps[] = null;
-    gps = getDisplayedFeatureGroups();
-    if (typ != null)
-    {
-      ArrayList types = new ArrayList();
-      for (int i = 0; i < typ.length; i++)
-      {
-        if (typ[i] != null)
-        {
-          types.add(typ[i]);
-        }
-        typ = new String[types.size()];
-        types.toArray(typ);
-      }
-    }
-    if (gps != null)
-    {
-      ArrayList grps = new ArrayList();
-
-      for (int i = 0; i < gps.length; i++)
-      {
-        if (gps[i] != null)
-        {
-          grps.add(gps[i]);
-        }
-      }
-      gps = new String[grps.size()];
-      grps.toArray(gps);
-    }
-    AlignmentPanel alignPanel = af.alignPanel;
-    AlignmentI al = alignPanel.av.getAlignment();
-
-    int start, stop;
-    SequenceGroup sg = alignPanel.av.getSelectionGroup();
-    if (sg != null)
-    {
-      start = sg.getStartRes();
-      stop = sg.getEndRes();
-    }
-    else
-    {
-      start = 0;
-      stop = al.getWidth();
-    }
-    SequenceI[] oldOrder = al.getSequencesArray();
-    AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
-    af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
-            .getAlignment()));
-    alignPanel.paintAlignment(true);
-
-  }
-
-  protected void sortByScore(String[] typ)
-  {
-    sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
-  }
-
-  private String[] getDisplayedFeatureTypes()
-  {
-    String[] typ = null;
-    if (fr != null)
-    {
-      synchronized (fr.renderOrder)
-      {
-        typ = new String[fr.renderOrder.length];
-        System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
-        for (int i = 0; i < typ.length; i++)
-        {
-          if (af.viewport.getFeaturesDisplayed().get(typ[i]) == null)
-          {
-            typ[i] = null;
-          }
-        }
-      }
-    }
-    return typ;
-  }
-
-  private String[] getDisplayedFeatureGroups()
-  {
-    String[] gps = null;
-    ArrayList<String> _gps = new ArrayList<String>();
-    if (fr != null)
-    {
-
-      if (fr.featureGroups != null)
-      {
-        Iterator en = fr.featureGroups.keySet().iterator();
-        int g = 0;
-        boolean valid = false;
-        while (en.hasNext())
-        {
-          String gp = (String) en.next();
-          Boolean on = (Boolean) fr.featureGroups.get(gp);
-          if (on != null && on.booleanValue())
-          {
-            valid = true;
-            _gps.add(gp);
-          }
-        }
-        if (!valid)
-        {
-          return null;
-        }
-        else
-        {
-          gps = new String[_gps.size()];
-          _gps.toArray(gps);
-        }
-      }
-    }
-    return gps;
-  }
-
   public void fetchDAS_actionPerformed(ActionEvent e)
   {
     fetchDAS.setEnabled(false);
@@ -1290,7 +1249,7 @@ public class FeatureSettings extends JPanel
   {
     SequenceI[] dataset, seqs;
     int iSize;
-    AlignViewport vp = af.getViewport();
+    AlignmentViewport vp = af.getViewport();
     if (vp.getSelectionGroup() != null
             && vp.getSelectionGroup().getSize() > 0)
     {
@@ -1375,6 +1334,7 @@ public class FeatureSettings extends JPanel
       Runnable fetcher = new Runnable()
       {
 
+        @Override
         public void run()
         {
           doDasFeatureFetch(dassources, true, false);
@@ -1439,8 +1399,10 @@ public class FeatureSettings extends JPanel
       this.data = data;
     }
 
-    private String[] columnNames =
-    { MessageManager.getString("label.feature_type"), MessageManager.getString("action.colour"), MessageManager.getString("label.display") };
+    private String[] columnNames = {
+        MessageManager.getString("label.feature_type"),
+        MessageManager.getString("action.colour"),
+        MessageManager.getString("label.display") };
 
     private Object[][] data;
 
@@ -1454,6 +1416,7 @@ public class FeatureSettings extends JPanel
       this.data = data;
     }
 
+    @Override
     public int getColumnCount()
     {
       return columnNames.length;
@@ -1464,31 +1427,37 @@ public class FeatureSettings extends JPanel
       return data[row];
     }
 
+    @Override
     public int getRowCount()
     {
       return data.length;
     }
 
+    @Override
     public String getColumnName(int col)
     {
       return columnNames[col];
     }
 
+    @Override
     public Object getValueAt(int row, int col)
     {
       return data[row][col];
     }
 
+    @Override
     public Class getColumnClass(int c)
     {
       return getValueAt(0, c).getClass();
     }
 
+    @Override
     public boolean isCellEditable(int row, int col)
     {
       return col == 0 ? false : true;
     }
 
+    @Override
     public void setValueAt(Object value, int row, int col)
     {
       data[row][col] = value;
@@ -1513,6 +1482,7 @@ public class FeatureSettings extends JPanel
       setVerticalTextPosition(SwingConstants.CENTER);
     }
 
+    @Override
     public Component getTableCellRendererComponent(JTable table,
             Object color, boolean isSelected, boolean hasFocus, int row,
             int column)
@@ -1678,16 +1648,19 @@ class FeatureIcon implements Icon
     }
   }
 
+  @Override
   public int getIconWidth()
   {
     return width;
   }
 
+  @Override
   public int getIconHeight()
   {
     return height;
   }
 
+  @Override
   public void paintIcon(Component c, Graphics g, int x, int y)
   {
 
@@ -1768,6 +1741,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
   /**
    * Handles events from the editor button and from the dialog's OK button.
    */
+  @Override
   public void actionPerformed(ActionEvent e)
   {
 
@@ -1813,6 +1787,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
   }
 
   // Implement the one CellEditor method that AbstractCellEditor doesn't.
+  @Override
   public Object getCellEditorValue()
   {
     if (currentColor == null)
@@ -1823,6 +1798,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
   }
 
   // Implement the one method defined by TableCellEditor.
+  @Override
   public Component getTableCellEditorComponent(JTable table, Object value,
           boolean isSelected, int row, int column)
   {