JAL-3187 better semantics for feature settings closed event handler
[jalview.git] / src / jalview / gui / FeatureSettings.java
index a1d9a04..961ff14 100644 (file)
  */
 package jalview.gui;
 
+import jalview.api.AlignViewControllerGuiI;
+import jalview.api.AlignViewportI;
 import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsControllerI;
+import jalview.api.SplitContainerI;
+import jalview.api.ViewStyleI;
+import jalview.controller.FeatureSettingsControllerGuiI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.features.FeatureMatcher;
@@ -31,18 +36,21 @@ import jalview.datamodel.features.FeatureMatcherSetI;
 import jalview.gui.Help.HelpId;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
-import jalview.schemabinding.version2.Filter;
-import jalview.schemabinding.version2.JalviewUserColours;
-import jalview.schemabinding.version2.MatcherSet;
 import jalview.schemes.FeatureColour;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
+import jalview.viewmodel.styles.ViewStyle;
+import jalview.xml.binding.jalview.JalviewUserColours;
+import jalview.xml.binding.jalview.JalviewUserColours.Colour;
+import jalview.xml.binding.jalview.JalviewUserColours.Filter;
+import jalview.xml.binding.jalview.ObjectFactory;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.GridLayout;
@@ -79,7 +87,6 @@ import javax.swing.BorderFactory;
 import javax.swing.Icon;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
-import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JDialog;
 import javax.swing.JInternalFrame;
@@ -97,12 +104,18 @@ import javax.swing.border.Border;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 import javax.swing.table.AbstractTableModel;
+import javax.swing.table.JTableHeader;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Marshaller;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
 
 public class FeatureSettings extends JPanel
-        implements FeatureSettingsControllerI
+        implements FeatureSettingsControllerI, FeatureSettingsControllerGuiI
 {
   private static final String SEQUENCE_FEATURE_COLOURS = MessageManager
           .getString("label.sequence_feature_colours");
@@ -124,7 +137,7 @@ public class FeatureSettings extends JPanel
 
   private static final int MIN_HEIGHT = 400;
 
-  private final static String BASE_TOOLTIP = "Click to edit, right-click for menu";
+  private final static String BASE_TOOLTIP = MessageManager.getString("label.click_to_edit");
 
   final FeatureRenderer fr;
 
@@ -137,6 +150,8 @@ public class FeatureSettings extends JPanel
 
   private float originalTransparency;
 
+  private ViewStyleI originalViewStyle;
+
   private Map<String, FeatureMatcherSetI> originalFilters;
 
   final JInternalFrame frame;
@@ -156,12 +171,6 @@ public class FeatureSettings extends JPanel
 
   int selectedRow = -1;
 
-  JButton fetchDAS = new JButton();
-
-  JButton saveDAS = new JButton();
-
-  JButton cancelDAS = new JButton();
-
   boolean resettingTable = false;
 
   /*
@@ -190,6 +199,7 @@ public class FeatureSettings extends JPanel
     transparency.setMaximum(100 - originalTransparencyAsPercent);
 
     originalFilters = new HashMap<>(fr.getFeatureFilters()); // shallow copy
+    originalViewStyle = new ViewStyle(af.viewport.getViewStyle());
 
     try
     {
@@ -201,8 +211,6 @@ public class FeatureSettings extends JPanel
 
     table = new JTable()
     {
-      static final String tt = "Click to edit, right-click for menu"; // todo i18n
-      
       @Override
       public String getToolTipText(MouseEvent e)
       {
@@ -219,27 +227,43 @@ public class FeatureSettings extends JPanel
         case COLOUR_COLUMN:
           FeatureColourI colour = (FeatureColourI) table.getValueAt(row,
                   column);
-          tip = getColorTooltip(colour);
+          tip = getColorTooltip(colour, true);
           break;
         case FILTER_COLUMN:
           FeatureMatcherSet o = (FeatureMatcherSet) table.getValueAt(row,
                   column);
           tip = o.isEmpty()
-                  ? MessageManager.getString("label.filters_tooltip")
+                  ? MessageManager
+                          .getString("label.configure_feature_tooltip")
                   : o.toString();
           break;
         default:
           break;
         }
+        
         return tip;
       }
+
+      /**
+       * Position the tooltip near the bottom edge of, and half way across, the
+       * current cell
+       */
+      @Override
+      public Point getToolTipLocation(MouseEvent e)
+      {
+        Point point = e.getPoint();
+        int column = table.columnAtPoint(point);
+        int row = table.rowAtPoint(point);
+        Rectangle r = getCellRect(row, column, false);
+        Point loc = new Point(r.x + r.width / 2, r.y + r.height - 3);
+        return loc;
+      }
     };
-    table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
+    JTableHeader tableHeader = table.getTableHeader();
+    tableHeader.setFont(new Font("Verdana", Font.PLAIN, 12));
+    tableHeader.setReorderingAllowed(false);
     table.setFont(new Font("Verdana", Font.PLAIN, 12));
 
-    // table.setDefaultRenderer(Color.class, new ColorRenderer());
-    // table.setDefaultEditor(Color.class, new ColorEditor(this));
-    //
     table.setDefaultEditor(FeatureColour.class, new ColorEditor(this));
     table.setDefaultRenderer(FeatureColour.class, new ColorRenderer());
 
@@ -261,7 +285,8 @@ public class FeatureSettings extends JPanel
       @Override
       public void mousePressed(MouseEvent evt)
       {
-        selectedRow = table.rowAtPoint(evt.getPoint());
+        Point pt = evt.getPoint();
+        selectedRow = table.rowAtPoint(pt);
         String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
         if (evt.isPopupTrigger())
         {
@@ -269,13 +294,15 @@ public class FeatureSettings extends JPanel
           popupSort(selectedRow, type, colour, fr.getMinMax(), evt.getX(),
                   evt.getY());
         }
-        else if (evt.getClickCount() == 2)
+        else if (evt.getClickCount() == 2
+                && table.columnAtPoint(pt) == TYPE_COLUMN)
         {
           boolean invertSelection = evt.isAltDown();
           boolean toggleSelection = Platform.isControlDown(evt);
           boolean extendSelection = evt.isShiftDown();
           fr.ap.alignFrame.avc.markColumnsContainingFeatures(
                   invertSelection, extendSelection, toggleSelection, type);
+          fr.ap.av.sendSelection();
         }
       }
 
@@ -332,7 +359,6 @@ public class FeatureSettings extends JPanel
     }
 
     discoverAllFeatureData();
-    final PropertyChangeListener change;
     final FeatureSettings fs = this;
     fr.addPropertyChangeListener(change = new PropertyChangeListener()
     {
@@ -349,43 +375,64 @@ public class FeatureSettings extends JPanel
       }
 
     });
-
-    frame = new JInternalFrame();
-    frame.setContentPane(this);
-    if (Platform.isAMac())
+    SplitContainerI splitframe = af.getSplitViewContainer();
+    if (splitframe != null)
     {
-      Desktop.addInternalFrame(frame,
-              MessageManager.getString("label.sequence_feature_settings"),
-              600, 480);
+      frame = null; // keeps eclipse happy
+      splitframe.addFeatureSettingsUI(this);
     }
     else
     {
-      Desktop.addInternalFrame(frame,
-              MessageManager.getString("label.sequence_feature_settings"),
-              600, 450);
-    }
-    frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
+      frame = new JInternalFrame();
+      frame.setContentPane(this);
+      if (Platform.isAMac())
+      {
+        Desktop.addInternalFrame(frame,
+                MessageManager.getString("label.sequence_feature_settings"),
+                600, 480);
+      }
+      else
+      {
+        Desktop.addInternalFrame(frame,
+                MessageManager.getString("label.sequence_feature_settings"),
+                600, 450);
+      }
+      frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
 
-    frame.addInternalFrameListener(
-            new javax.swing.event.InternalFrameAdapter()
-            {
-              @Override
-              public void internalFrameClosed(
-                      javax.swing.event.InternalFrameEvent evt)
+      frame.addInternalFrameListener(
+              new javax.swing.event.InternalFrameAdapter()
               {
-                fr.removePropertyChangeListener(change);
-              };
-            });
-    frame.setLayer(JLayeredPane.PALETTE_LAYER);
+                @Override
+                public void internalFrameClosed(
+                        javax.swing.event.InternalFrameEvent evt)
+                {
+                  featureSettings_isClosed();
+                };
+              });
+      frame.setLayer(JLayeredPane.PALETTE_LAYER);
+    }
     inConstruction = false;
   }
 
+  PropertyChangeListener change;
+
+  @Override
+  public AlignViewControllerGuiI getAlignframe()
+  {
+    return af;
+  }
+
+  @Override
+  public void featureSettings_isClosed()
+  {
+    fr.removePropertyChangeListener(change);
+    change = null;
+  }
+
   protected void popupSort(final int rowSelected, final String type,
           final Object typeCol, final Map<String, float[][]> minmax, int x,
           int y)
   {
-    final FeatureColourI featureColour = (FeatureColourI) typeCol;
-
     JPopupMenu men = new JPopupMenu(MessageManager
             .formatMessage("label.settings_for_param", new String[]
             { type }));
@@ -421,69 +468,6 @@ public class FeatureSettings extends JPanel
     });
     men.add(dens);
 
-    /*
-     * variable colour options include colour by label, by score,
-     * by selected attribute text, or attribute value
-     */
-    final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
-            MessageManager.getString("label.variable_colour"));
-    mxcol.setSelected(!featureColour.isSimpleColour());
-    men.add(mxcol);
-    mxcol.addActionListener(new ActionListener()
-    {
-      JColorChooser colorChooser;
-
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        if (e.getSource() == mxcol)
-        {
-          if (featureColour.isSimpleColour())
-          {
-            FeatureTypeSettings fc = new FeatureTypeSettings(me.fr, type);
-            fc.addActionListener(this);
-          }
-          else
-          {
-            // bring up simple color chooser
-            colorChooser = new JColorChooser();
-            String title = MessageManager
-                    .getString("label.select_colour");
-            JDialog dialog = JColorChooser.createDialog(me,
-                    title, true, // modal
-                    colorChooser, this, // OK button handler
-                    null); // no CANCEL button handler
-            colorChooser.setColor(featureColour.getMaxColour());
-            dialog.setVisible(true);
-          }
-        }
-        else
-        {
-          if (e.getSource() instanceof FeatureTypeSettings)
-          {
-            /*
-             * update after OK in feature colour dialog; the updated
-             * colour will have already been set in the FeatureRenderer
-             */
-            FeatureColourI fci = fr.getFeatureColours().get(type);
-            table.setValueAt(fci, rowSelected, 1);
-            table.validate();
-          }
-          else
-          {
-            // probably the color chooser!
-            table.setValueAt(new FeatureColour(colorChooser.getColor()),
-                    rowSelected, 1);
-            table.validate();
-            me.updateFeatureRenderer(
-                    ((FeatureTableModel) table.getModel()).getData(),
-                    false);
-          }
-        }
-      }
-
-    });
-
     JMenuItem selCols = new JMenuItem(
             MessageManager.getString("label.select_columns_containing"));
     selCols.addActionListener(new ActionListener()
@@ -493,6 +477,7 @@ public class FeatureSettings extends JPanel
       {
         fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
                 false, type);
+        fr.ap.av.sendSelection();
       }
     });
     JMenuItem clearCols = new JMenuItem(MessageManager
@@ -504,6 +489,7 @@ public class FeatureSettings extends JPanel
       {
         fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
                 false, type);
+        fr.ap.av.sendSelection();
       }
     });
     JMenuItem hideCols = new JMenuItem(
@@ -514,6 +500,7 @@ public class FeatureSettings extends JPanel
       public void actionPerformed(ActionEvent arg0)
       {
         fr.ap.alignFrame.hideFeatureColumns(type, true);
+        fr.ap.av.sendSelection();
       }
     });
     JMenuItem hideOtherCols = new JMenuItem(
@@ -524,6 +511,7 @@ public class FeatureSettings extends JPanel
       public void actionPerformed(ActionEvent arg0)
       {
         fr.ap.alignFrame.hideFeatureColumns(type, false);
+        fr.ap.av.sendSelection();
       }
     });
     men.add(selCols);
@@ -587,7 +575,7 @@ public class FeatureSettings extends JPanel
       {
         fr.setGroupVisibility(check.getText(), check.isSelected());
         resetTable(new String[] { grp });
-        af.alignPanel.paintAlignment(true, true);
+        refreshDisplay();
       }
     });
     groupPanel.add(check);
@@ -685,7 +673,7 @@ public class FeatureSettings extends JPanel
         data[dataIndex][FILTER_COLUMN] = featureFilter == null
                 ? new FeatureMatcherSet()
                 : featureFilter;
-        data[dataIndex][SHOW_COLUMN] = new Boolean(
+        data[dataIndex][SHOW_COLUMN] = Boolean.valueOf(
                 af.getViewport().getFeaturesDisplayed().isVisible(type));
         dataIndex++;
         displayableTypes.remove(type);
@@ -712,7 +700,7 @@ public class FeatureSettings extends JPanel
       data[dataIndex][FILTER_COLUMN] = featureFilter == null
               ? new FeatureMatcherSet()
               : featureFilter;
-      data[dataIndex][SHOW_COLUMN] = new Boolean(true);
+      data[dataIndex][SHOW_COLUMN] = Boolean.valueOf(true);
       dataIndex++;
       displayableTypes.remove(type);
     }
@@ -886,30 +874,39 @@ public class FeatureSettings extends JPanel
       InputStreamReader in = new InputStreamReader(
               new FileInputStream(file), "UTF-8");
 
-      JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
+      JAXBContext jc = JAXBContext
+              .newInstance("jalview.xml.binding.jalview");
+      javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
+      XMLStreamReader streamReader = XMLInputFactory.newInstance()
+              .createXMLStreamReader(in);
+      JAXBElement<JalviewUserColours> jbe = um.unmarshal(streamReader,
+              JalviewUserColours.class);
+      JalviewUserColours jucs = jbe.getValue();
+
+      // JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
 
       /*
        * load feature colours
        */
-      for (int i = jucs.getColourCount() - 1; i >= 0; i--)
+      for (int i = jucs.getColour().size() - 1; i >= 0; i--)
       {
-        jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
-        FeatureColourI colour = Jalview2XML.unmarshalColour(newcol);
+        Colour newcol = jucs.getColour().get(i);
+        FeatureColourI colour = jalview.project.Jalview2XML
+                .parseColour(newcol);
         fr.setColour(newcol.getName(), colour);
-        fr.setOrder(newcol.getName(), i / (float) jucs.getColourCount());
+        fr.setOrder(newcol.getName(), i / (float) jucs.getColour().size());
       }
 
       /*
        * load feature filters; loaded filters will replace any that are
        * currently defined, other defined filters are left unchanged 
        */
-      for (int i = 0; i < jucs.getFilterCount(); i++)
+      for (int i = 0; i < jucs.getFilter().size(); i++)
       {
-        jalview.schemabinding.version2.Filter filterModel = jucs
-                .getFilter(i);
+        Filter filterModel = jucs.getFilter().get(i);
         String featureType = filterModel.getFeatureType();
-        FeatureMatcherSetI filter = Jalview2XML.unmarshalFilter(featureType,
-                filterModel.getMatcherSet());
+        FeatureMatcherSetI filter = jalview.project.Jalview2XML
+                .parseFilter(featureType, filterModel.getMatcherSet());
         if (!filter.isEmpty())
         {
           fr.setFeatureFilter(featureType, filter);
@@ -991,9 +988,9 @@ public class FeatureSettings extends JPanel
       for (String featureType : sortedTypes)
       {
         FeatureColourI fcol = fr.getFeatureStyle(featureType);
-        jalview.schemabinding.version2.Colour col = Jalview2XML.marshalColour(
-                featureType, fcol);
-        ucs.addColour(col);
+        Colour col = jalview.project.Jalview2XML.marshalColour(featureType,
+                fcol);
+        ucs.getColour().add(col);
       }
 
       /*
@@ -1006,16 +1003,26 @@ public class FeatureSettings extends JPanel
         {
           Iterator<FeatureMatcherI> iterator = filter.getMatchers().iterator();
           FeatureMatcherI firstMatcher = iterator.next();
-          MatcherSet ms = Jalview2XML.marshalFilter(firstMatcher, iterator,
+          jalview.xml.binding.jalview.FeatureMatcherSet ms = jalview.project.Jalview2XML
+                  .marshalFilter(firstMatcher, iterator,
                   filter.isAnded());
           Filter filterModel = new Filter();
           filterModel.setFeatureType(featureType);
           filterModel.setMatcherSet(ms);
-          ucs.addFilter(filterModel);
+          ucs.getFilter().add(filterModel);
         }
       }
+      JAXBContext jaxbContext = JAXBContext
+              .newInstance(JalviewUserColours.class);
+      Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+      jaxbMarshaller.marshal(
+              new ObjectFactory().createJalviewUserColours(ucs), out);
+
+      // jaxbMarshaller.marshal(object, pout);
+      // marshaller.marshal(object);
+      out.flush();
 
-      ucs.marshal(out);
+      // ucs.marshal(out);
       out.close();
     } catch (Exception ex)
     {
@@ -1101,7 +1108,16 @@ public class FeatureSettings extends JPanel
   {
     try
     {
-      frame.setClosed(true);
+      if (frame != null)
+      {
+        frame.setClosed(true);
+      }
+      else
+      {
+        SplitContainerI sc = af.getSplitViewContainer();
+        sc.closeFeatureSettings(this);
+        af.featureSettings = null;
+      }
     } catch (Exception exe)
     {
     }
@@ -1126,7 +1142,7 @@ public class FeatureSettings extends JPanel
 
     if (fr.setFeaturePriority(rowData, visibleNew))
     {
-      af.alignPanel.paintAlignment(true, true);
+      refreshDisplay();
     }
   }
 
@@ -1224,22 +1240,6 @@ public class FeatureSettings extends JPanel
         }
       }
     });
-    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();
-        }
-      }
-    });
 
     JButton cancel = new JButton(MessageManager.getString("action.cancel"));
     cancel.setFont(JvSwingUtils.getLabelFont());
@@ -1251,6 +1251,7 @@ public class FeatureSettings extends JPanel
         fr.setTransparency(originalTransparency);
         fr.setFeatureFilters(originalFilters);
         updateFeatureRenderer(originalData);
+        af.getViewport().setViewStyle(originalViewStyle);
         close();
       }
     });
@@ -1301,7 +1302,7 @@ public class FeatureSettings extends JPanel
         if (!inConstruction)
         {
           fr.setTransparency((100 - transparency.getValue()) / 100f);
-          af.alignPanel.paintAlignment(true, true);
+          refreshDisplay();
         }
       }
     });
@@ -1310,8 +1311,73 @@ public class FeatureSettings extends JPanel
     transparency.setToolTipText(
             MessageManager.getString("label.transparency_tip"));
 
-    JPanel transPanel = new JPanel(new GridLayout(1, 2));
-    bigPanel.add(transPanel, BorderLayout.SOUTH);
+    boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
+    String text = MessageManager.formatMessage("label.show_linked_features",
+            nucleotide
+                    ? MessageManager.getString("label.protein")
+                            .toLowerCase()
+                    : "CDS");
+    JCheckBox showComplement = new JCheckBox(text);
+    showComplement.setSelected(af.getViewport().isShowComplementFeatures());
+    showComplement.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        af.getViewport()
+                .setShowComplementFeatures(showComplement.isSelected());
+        refreshDisplay();
+      }
+    });
+
+    JCheckBox showComplementOnTop = new JCheckBox(
+            MessageManager.getString("label.on_top"));
+    showComplementOnTop
+            .setSelected(af.getViewport().isShowComplementFeaturesOnTop());
+    showComplementOnTop.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        af.getViewport().setShowComplementFeaturesOnTop(
+                showComplementOnTop.isSelected());
+        refreshDisplay();
+      }
+    });
+    // JButton viewComplementSettings = new JButton(MessageManager
+    // .formatMessage("label.show_linked_feature_settings",
+    // nucleotide
+    // ? MessageManager.getString("label.protein")
+    // .toLowerCase()
+    // : "CDS"));
+    // viewComplementSettings.addActionListener(new ActionListener()
+    // {
+    //
+    // @Override
+    // public void actionPerformed(ActionEvent e)
+    // {
+    // AlignViewControllerGuiI complAf = af.getSplitViewContainer()
+    // .getComplementAlignFrame(af);
+    // FeatureSettings complFeatureSettings = (FeatureSettings) complAf
+    // .getFeatureSettingsUI();
+    // if (complFeatureSettings != null)
+    // {
+    // complFeatureSettings.frame.setVisible(true);
+    // try
+    // {
+    // complFeatureSettings.frame.setSelected(true);
+    // return;
+    // } catch (Exception q)
+    // {
+    // }
+    // }
+    // {
+    // complAf.showFeatureSettingsUI();
+    // }
+    // }
+    // });
+    JPanel lowerPanel = new JPanel(new GridLayout(1, 2));
+    bigPanel.add(lowerPanel, BorderLayout.SOUTH);
 
     JPanel transbuttons = new JPanel(new GridLayout(5, 1));
     transbuttons.add(optimizeOrder);
@@ -1319,8 +1385,21 @@ public class FeatureSettings extends JPanel
     transbuttons.add(sortByScore);
     transbuttons.add(sortByDens);
     transbuttons.add(help);
-    transPanel.add(transparency);
-    transPanel.add(transbuttons);
+
+    boolean hasComplement = af.getViewport().getCodingComplement() != null;
+    JPanel transPanelLeft = new JPanel(
+            new GridLayout(hasComplement ? 4 : 2, 1));
+    transPanelLeft.add(new JLabel(" Colour transparency" + ":"));
+    transPanelLeft.add(transparency);
+    if (hasComplement)
+    {
+      JPanel cp = new JPanel(new FlowLayout(FlowLayout.LEFT));
+      cp.add(showComplement);
+      cp.add(showComplementOnTop);
+      transPanelLeft.add(cp);
+    }
+    lowerPanel.add(transPanelLeft);
+    lowerPanel.add(transbuttons);
 
     JPanel buttonPanel = new JPanel();
     buttonPanel.add(ok);
@@ -1334,12 +1413,31 @@ public class FeatureSettings extends JPanel
   }
 
   /**
+   * Repaints alignment, structure and overview (if shown). If there is a
+   * complementary view which is showing this view's features, then also
+   * repaints that.
+   */
+  void refreshDisplay()
+  {
+    af.alignPanel.paintAlignment(true, true);
+    AlignViewportI complement = af.getViewport().getCodingComplement();
+    if (complement != null && complement.isShowComplementFeatures())
+    {
+      AlignFrame af2 = Desktop.getAlignFrameFor(complement);
+      af2.alignPanel.paintAlignment(true, true);
+    }
+  }
+
+  /**
    * Answers a suitable tooltip to show on the colour cell of the table
    * 
    * @param fcol
+   * @param withHint
+   *                   if true include 'click to edit' and similar text
    * @return
    */
-  public static String getColorTooltip(FeatureColourI fcol)
+  public static String getColorTooltip(FeatureColourI fcol,
+          boolean withHint)
   {
     if (fcol == null)
     {
@@ -1347,13 +1445,16 @@ public class FeatureSettings extends JPanel
     }
     if (fcol.isSimpleColour())
     {
-      return BASE_TOOLTIP;
+      return withHint ? BASE_TOOLTIP : null;
     }
     String description = fcol.getDescription();
     description = description.replaceAll("<", "&lt;");
     description = description.replaceAll(">", "&gt;");
     StringBuilder tt = new StringBuilder(description);
-    tt.append("<br>").append(BASE_TOOLTIP).append("</br>");
+    if (withHint)
+    {
+      tt.append("<br>").append(BASE_TOOLTIP).append("</br>");
+    }
     return JvSwingUtils.wrapTooltip(true, tt.toString());
   }
 
@@ -1419,7 +1520,7 @@ public class FeatureSettings extends JPanel
     private String[] columnNames = {
         MessageManager.getString("label.feature_type"),
         MessageManager.getString("action.colour"),
-        MessageManager.getString("label.filter"),
+        MessageManager.getString("label.configuration"),
         MessageManager.getString("label.show") };
 
     private Object[][] data;
@@ -1469,13 +1570,22 @@ public class FeatureSettings extends JPanel
     }
 
     /**
-     * Answers the class of the object in column c of the first row of the table
+     * Answers the class of column c of the table
      */
     @Override
     public Class<?> getColumnClass(int c)
     {
-      Object v = getValueAt(0, c);
-      return v == null ? null : v.getClass();
+      switch (c)
+      {
+      case TYPE_COLUMN:
+        return String.class;
+      case COLOUR_COLUMN:
+        return FeatureColour.class;
+      case FILTER_COLUMN:
+        return FeatureMatcherSet.class;
+      default:
+        return Boolean.class;
+      }
     }
 
     @Override
@@ -1681,14 +1791,17 @@ public class FeatureSettings extends JPanel
         {
           // bring up graduated chooser.
           chooser = new FeatureTypeSettings(me.fr, type);
-          chooser.setRequestFocusEnabled(true);
-          chooser.requestFocus();
+          /**
+           * @j2sNative
+           */
+          {
+            chooser.setRequestFocusEnabled(true);
+            chooser.requestFocus();
+          }
           chooser.addActionListener(this);
-          chooser.showTab(true);
+          // Make the renderer reappear.
+          fireEditingStopped();
         }
-        // Make the renderer reappear.
-        fireEditingStopped();
-
       }
       else
       {
@@ -1810,7 +1923,6 @@ public class FeatureSettings extends JPanel
                   chooser.getWidth(), chooser.getHeight());
           chooser.validate();
         }
-        chooser.showTab(false);
         fireEditingStopped();
       }
       else if (e.getSource() instanceof Component)