JAL-3541 selectively merged build.gradle and gradle.properties
[jalview.git] / src / jalview / gui / FeatureSettings.java
index b87e4bf..b49593a 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;
-import jalview.datamodel.features.FeatureMatcherI;
-import jalview.datamodel.features.FeatureMatcherSet;
-import jalview.datamodel.features.FeatureMatcherSetI;
-import jalview.gui.Help.HelpId;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-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;
@@ -87,8 +61,7 @@ import javax.swing.BorderFactory;
 import javax.swing.Icon;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
-import javax.swing.JColorChooser;
-import javax.swing.JDialog;
+import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JInternalFrame;
 import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
@@ -100,6 +73,7 @@ import javax.swing.JSlider;
 import javax.swing.JTable;
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingConstants;
+import javax.swing.ToolTipManager;
 import javax.swing.border.Border;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
@@ -114,6 +88,33 @@ import javax.xml.bind.Marshaller;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
 
+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;
+import jalview.datamodel.features.FeatureMatcherI;
+import jalview.datamodel.features.FeatureMatcherSet;
+import jalview.datamodel.features.FeatureMatcherSetI;
+import jalview.gui.Help.HelpId;
+import jalview.gui.JalviewColourChooser.ColourChooserListener;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+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;
+
 public class FeatureSettings extends JPanel
         implements FeatureSettingsControllerI, FeatureSettingsControllerGuiI
 {
@@ -137,7 +138,8 @@ public class FeatureSettings extends JPanel
 
   private static final int MIN_HEIGHT = 400;
 
-  private final static String BASE_TOOLTIP = MessageManager.getString("label.click_to_edit");
+  private final static String BASE_TOOLTIP = MessageManager
+          .getString("label.click_to_edit");
 
   final FeatureRenderer fr;
 
@@ -148,7 +150,7 @@ public class FeatureSettings extends JPanel
    */
   Object[][] originalData;
 
-  private float originalTransparency;
+  float originalTransparency;
 
   private ViewStyleI originalViewStyle;
 
@@ -180,7 +182,7 @@ public class FeatureSettings extends JPanel
   /*
    * true when Feature Settings are updating from feature renderer
    */
-  private boolean handlingUpdate = false;
+  boolean handlingUpdate = false;
 
   /*
    * a change listener to ensure the dialog is updated if
@@ -264,7 +266,7 @@ public class FeatureSettings extends JPanel
         default:
           break;
         }
-        
+
         return tip;
       }
 
@@ -287,19 +289,19 @@ public class FeatureSettings extends JPanel
     tableHeader.setFont(new Font("Verdana", Font.PLAIN, 12));
     tableHeader.setReorderingAllowed(false);
     table.setFont(new Font("Verdana", Font.PLAIN, 12));
-
-    table.setDefaultEditor(FeatureColour.class, new ColorEditor(this));
+    ToolTipManager.sharedInstance().registerComponent(table);
+    table.setDefaultEditor(FeatureColour.class, new ColorEditor());
     table.setDefaultRenderer(FeatureColour.class, new ColorRenderer());
 
-    table.setDefaultEditor(FeatureMatcherSet.class, new FilterEditor(this));
+    table.setDefaultEditor(FeatureMatcherSet.class, new FilterEditor());
     table.setDefaultRenderer(FeatureMatcherSet.class, new FilterRenderer());
 
     TableColumn colourColumn = new TableColumn(COLOUR_COLUMN, 75,
-            new ColorRenderer(), new ColorEditor(this));
+            new ColorRenderer(), new ColorEditor());
     table.addColumn(colourColumn);
 
     TableColumn filterColumn = new TableColumn(FILTER_COLUMN, 75,
-            new FilterRenderer(), new FilterEditor(this));
+            new FilterRenderer(), new FilterEditor());
     table.addColumn(filterColumn);
 
     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
@@ -315,8 +317,7 @@ public class FeatureSettings extends JPanel
         if (evt.isPopupTrigger())
         {
           Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
-          popupSort(selectedRow, type, colour, fr.getMinMax(), evt.getX(),
-                  evt.getY());
+          showPopupMenu(selectedRow, type, colour, evt.getPoint());
         }
         else if (evt.getClickCount() == 2
                 && table.columnAtPoint(pt) == TYPE_COLUMN)
@@ -339,8 +340,7 @@ public class FeatureSettings extends JPanel
         {
           String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
           Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
-          popupSort(selectedRow, type, colour, fr.getMinMax(), evt.getX(),
-                  evt.getY());
+          showPopupMenu(selectedRow, type, colour, evt.getPoint());
         }
       }
     });
@@ -399,6 +399,7 @@ public class FeatureSettings extends JPanel
       }
 
     });
+
     SplitContainerI splitframe = af.getSplitViewContainer();
     if (splitframe != null)
     {
@@ -424,7 +425,7 @@ public class FeatureSettings extends JPanel
       }
       if (bounds == null)
       {
-        if (Platform.isAMac())
+        if (Platform.isAMacAndNotJS())
         {
           Desktop.addInternalFrame(frame, title, 600, 480);
         }
@@ -435,8 +436,8 @@ public class FeatureSettings extends JPanel
       }
       else
       {
-        Desktop.addInternalFrame(frame, title,
-                false, bounds.width, bounds.height);
+        Desktop.addInternalFrame(frame, title, false, bounds.width,
+                bounds.height);
         frame.setBounds(bounds);
         frame.setVisible(true);
       }
@@ -454,8 +455,8 @@ public class FeatureSettings extends JPanel
               });
       frame.setLayer(JLayeredPane.PALETTE_LAYER);
     }
-    inConstruction = false;
-  }
+               inConstruction = false;
+       }
 
   /**
    * Sets the state of buttons to show complement features from viewport
@@ -481,13 +482,96 @@ public class FeatureSettings extends JPanel
     change = null;
   }
 
-  protected void popupSort(final int rowSelected, final String type,
-          final Object typeCol, final Map<String, float[][]> minmax, int x,
-          int y)
+       /**
+        * Constructs and shows a popup menu of possible actions on the selected row and
+        * feature type
+        * 
+        * @param rowSelected
+        * @param type
+        * @param typeCol
+        * @param pt
+        */
+       protected void showPopupMenu(final int rowSelected, final String type, final Object typeCol, final Point pt)
   {
     JPopupMenu men = new JPopupMenu(MessageManager
             .formatMessage("label.settings_for_param", new String[]
             { type }));
+    final FeatureColourI featureColour = (FeatureColourI) typeCol;
+
+    /*
+     * menu option to select (or deselect) variable colour
+     */
+    final JCheckBoxMenuItem variableColourCB = new JCheckBoxMenuItem(
+            MessageManager.getString("label.variable_colour"));
+    variableColourCB.setSelected(!featureColour.isSimpleColour());
+    men.add(variableColourCB);
+
+    /*
+     * checkbox action listener doubles up as listener to OK
+     * from the variable colour / filters dialog
+     */
+    variableColourCB.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (e.getSource() == variableColourCB)
+        {
+                                       // BH 2018 for JavaScript because this is a checkbox
+                                       men.setVisible(true);
+          men.setVisible(false);
+          if (featureColour.isSimpleColour())
+          {
+            /*
+             * toggle simple colour to variable colour - show dialog
+             */
+            FeatureTypeSettings fc = new FeatureTypeSettings(fr, type);
+            fc.addActionListener(this);
+          }
+          else
+          {
+            /*
+             * toggle variable to simple colour - show colour chooser
+             */
+            String title = MessageManager
+                    .formatMessage("label.select_colour_for", type);
+            ColourChooserListener listener = new ColourChooserListener()
+            {
+              @Override
+              public void colourSelected(Color c)
+              {
+                table.setValueAt(new FeatureColour(c), rowSelected,
+                        COLOUR_COLUMN);
+                table.validate();
+                updateFeatureRenderer(
+                        ((FeatureTableModel) table.getModel()).getData(),
+                        false);
+              }
+            };
+            JalviewColourChooser.showColourChooser(FeatureSettings.this,
+                    title, featureColour.getMaxColour(), listener);
+          }
+        }
+        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, COLOUR_COLUMN);
+            // BH 2018 setting a table value does not invalidate it.
+            // System.out.println("FeatureSettings is valied" +
+            // table.validate();
+          }
+        }
+      }
+    });
+
+    men.addSeparator();
+
     JMenuItem scr = new JMenuItem(
             MessageManager.getString("label.sort_by_score"));
     men.add(scr);
@@ -561,7 +645,7 @@ public class FeatureSettings extends JPanel
     men.add(clearCols);
     men.add(hideCols);
     men.add(hideOtherCols);
-    men.show(table, x, y);
+    men.show(table, pt.x, pt.y);
   }
 
   /**
@@ -815,8 +899,8 @@ public class FeatureSettings extends JPanel
   }
 
   /**
-   * Updates 'originalData' (used for restore on Cancel) if we detect that changes
-   * have been made outwith this dialog
+   * Updates 'originalData' (used for restore on Cancel) if we detect that
+   * changes have been made outwith this dialog
    * <ul>
    * <li>a new feature type added (and made visible)</li>
    * <li>a feature colour changed (in the Amend Features dialog)</li>
@@ -880,8 +964,8 @@ public class FeatureSettings extends JPanel
 
   /**
    * Remove from the groups panel any checkboxes for groups that are not in the
-   * foundGroups set. This enables removing a group from the display when the last
-   * feature in that group is deleted.
+   * foundGroups set. This enables removing a group from the display when the
+   * last feature in that group is deleted.
    * 
    * @param foundGroups
    */
@@ -936,14 +1020,16 @@ public class FeatureSettings extends JPanel
     chooser.setDialogTitle(
             MessageManager.getString("label.load_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.load"));
-
-    int value = chooser.showOpenDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    chooser.setResponseHandler(0, new Runnable()
     {
-      File file = chooser.getSelectedFile();
-      load(file);
-    }
+      @Override
+      public void run()
+      {
+        File file = chooser.getSelectedFile();
+        load(file);
+      }
+    });
+    chooser.showOpenDialog(this);
   }
 
   /**
@@ -1003,8 +1089,7 @@ public class FeatureSettings extends JPanel
       if (table != null)
       {
         resetTable(null);
-        Object[][] data = ((FeatureTableModel) table.getModel())
-                .getData();
+        Object[][] data = ((FeatureTableModel) table.getModel()).getData();
         ensureOrder(data);
         updateFeatureRenderer(data, false);
         table.repaint();
@@ -1027,12 +1112,11 @@ public class FeatureSettings extends JPanel
     chooser.setDialogTitle(
             MessageManager.getString("label.save_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    int option = chooser.showSaveDialog(this);
+    if (option == JalviewFileChooser.APPROVE_OPTION)
     {
-      save(chooser.getSelectedFile());
+      File file = chooser.getSelectedFile();
+      save(file);
     }
   }
 
@@ -1047,8 +1131,8 @@ public class FeatureSettings extends JPanel
     ucs.setSchemeName("Sequence Features");
     try
     {
-      PrintWriter out = new PrintWriter(new OutputStreamWriter(
-              new FileOutputStream(file), "UTF-8"));
+      PrintWriter out = new PrintWriter(
+              new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
 
       /*
        * sort feature types by colour order, from 0 (highest)
@@ -1085,11 +1169,11 @@ public class FeatureSettings extends JPanel
         FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
         if (filter != null && !filter.isEmpty())
         {
-          Iterator<FeatureMatcherI> iterator = filter.getMatchers().iterator();
+          Iterator<FeatureMatcherI> iterator = filter.getMatchers()
+                  .iterator();
           FeatureMatcherI firstMatcher = iterator.next();
           jalview.xml.binding.jalview.FeatureMatcherSet ms = jalview.project.Jalview2XML
-                  .marshalFilter(firstMatcher, iterator,
-                  filter.isAnded());
+                  .marshalFilter(firstMatcher, iterator, filter.isAnded());
           Filter filterModel = new Filter();
           filterModel.setFeatureType(featureType);
           filterModel.setMatcherSet(ms);
@@ -1171,7 +1255,8 @@ public class FeatureSettings extends JPanel
       else
       {
         width[i] /= max; // normalize
-        fr.setOrder(data[i][TYPE_COLUMN].toString(), width[i]); // store for later
+        fr.setOrder(data[i][TYPE_COLUMN].toString(), width[i]); // store for
+                                                                // later
       }
       if (i > 0)
       {
@@ -1232,13 +1317,13 @@ public class FeatureSettings extends JPanel
   }
 
   /**
-   * Update the priority order of features; only repaint if this changed the order
-   * of visible features
+   * 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)
+  void updateFeatureRenderer(Object[][] data, boolean visibleNew)
   {
     FeatureSettingsBean[] rowData = getTableAsBeans(data);
 
@@ -1559,7 +1644,7 @@ public class FeatureSettings extends JPanel
   {
     boolean thr = false;
     StringBuilder tx = new StringBuilder();
-  
+
     if (gcol.isColourByAttribute())
     {
       tx.append(FeatureMatcher
@@ -1825,11 +1910,10 @@ public class FeatureSettings extends JPanel
     renderGraduatedColor(comp, gcol, w, h);
   }
 
+  @SuppressWarnings("serial")
   class ColorEditor extends AbstractCellEditor
           implements TableCellEditor, ActionListener
   {
-    FeatureSettings me;
-
     FeatureColourI currentColor;
 
     FeatureTypeSettings chooser;
@@ -1838,17 +1922,12 @@ public class FeatureSettings extends JPanel
 
     JButton button;
 
-    JColorChooser colorChooser;
-
-    JDialog dialog;
-
     protected static final String EDIT = "edit";
 
     int rowSelected = 0;
 
-    public ColorEditor(FeatureSettings me)
+    public ColorEditor()
     {
-      this.me = me;
       // Set up the editor (from the table's point of view),
       // which is a button.
       // This button brings up the color chooser dialog,
@@ -1857,81 +1936,99 @@ public class FeatureSettings extends JPanel
       button.setActionCommand(EDIT);
       button.addActionListener(this);
       button.setBorderPainted(false);
-      // Set up the dialog that the button brings up.
-      colorChooser = new JColorChooser();
-      dialog = JColorChooser.createDialog(button,
-              MessageManager.getString("label.select_colour"), true, // modal
-              colorChooser, this, // OK button handler
-              null); // no CANCEL button handler
     }
 
     /**
-     * Handles events from the editor button and from the dialog's OK button.
+     * Handles events from the editor button, and from the colour/filters
+     * dialog's OK button
      */
     @Override
     public void actionPerformed(ActionEvent e)
     {
-      // todo test e.getSource() instead here
-      if (EDIT.equals(e.getActionCommand()))
+      if (button == e.getSource())
       {
-        // The user has clicked the cell, so
-        // bring up the dialog.
         if (currentColor.isSimpleColour())
         {
-          // bring up simple color chooser
-          button.setBackground(currentColor.getColour());
-          colorChooser.setColor(currentColor.getColour());
-          dialog.setVisible(true);
+          /*
+           * simple colour chooser
+           */
+          String ttl = MessageManager
+                  .formatMessage("label.select_colour_for", type);
+          ColourChooserListener listener = new ColourChooserListener()
+          {
+            @Override
+            public void colourSelected(Color c)
+            {
+              currentColor = new FeatureColour(c);
+              table.setValueAt(currentColor, rowSelected, COLOUR_COLUMN);
+              fireEditingStopped();
+            }
+
+            @Override
+            public void cancel()
+            {
+              fireEditingStopped();
+            }
+          };
+          JalviewColourChooser.showColourChooser(button, ttl,
+                  currentColor.getColour(), listener);
         }
         else
         {
-          // bring up graduated chooser.
-          chooser = new FeatureTypeSettings(me.fr, type);
+          /*
+           * variable colour and filters dialog
+           */
+          chooser = new FeatureTypeSettings(fr, type);
+          if (!Platform.isJS())
           /**
-           * @j2sNative
+           * Java only
+           * 
+           * @j2sIgnore
            */
           {
             chooser.setRequestFocusEnabled(true);
             chooser.requestFocus();
           }
           chooser.addActionListener(this);
-          // Make the renderer reappear.
           fireEditingStopped();
         }
       }
       else
       {
-        if (currentColor.isSimpleColour())
-        {
-          /*
-           * read off colour picked in colour chooser after OK pressed
-           */
-          currentColor = new FeatureColour(colorChooser.getColor());
-          me.table.setValueAt(currentColor, rowSelected, COLOUR_COLUMN);
-        }
-        else
+        /*
+         * after OK in variable colour dialog, any changes to colour 
+         * (or filters!) are already set in FeatureRenderer, so just
+         * update table data without triggering updateFeatureRenderer
+         */
+        currentColor = fr.getFeatureColours().get(type);
+        FeatureMatcherSetI currentFilter = fr.getFeatureFilter(type);
+        if (currentFilter == null)
         {
-          /*
-           * after OK in variable colour dialog, any changes to colour 
-           * (or filters!) are already set in FeatureRenderer, so just
-           * update table data without triggering updateFeatureRenderer
-           */
-          currentColor = fr.getFeatureColours().get(type);
-          FeatureMatcherSetI currentFilter = me.fr.getFeatureFilter(type);
-          if (currentFilter == null)
-          {
-            currentFilter = new FeatureMatcherSet();
-          }
-          Object[] data = ((FeatureTableModel) table.getModel())
-                  .getData()[rowSelected];
-          data[COLOUR_COLUMN] = currentColor;
-          data[FILTER_COLUMN] = currentFilter;
+          currentFilter = new FeatureMatcherSet();
         }
+        Object[] data = ((FeatureTableModel) table.getModel())
+                .getData()[rowSelected];
+        data[COLOUR_COLUMN] = currentColor;
+        data[FILTER_COLUMN] = currentFilter;
         fireEditingStopped();
-        me.table.validate();
+        // SwingJS needs an explicit repaint() here,
+        // rather than relying upon no validation having
+        // occurred since the stopEditing call was made.
+        // Its laying out has not been stopped by the modal frame
+        table.validate();
+        table.repaint();
       }
     }
 
+    /**
+     * Override allows access to this method from anonymous inner classes
+     */
+    @Override
+    protected void fireEditingStopped()
+    {
+      super.fireEditingStopped();
+    }
+
     // Implement the one CellEditor method that AbstractCellEditor doesn't.
     @Override
     public Object getCellEditorValue()
@@ -1941,14 +2038,14 @@ public class FeatureSettings extends JPanel
 
     // Implement the one method defined by TableCellEditor.
     @Override
-    public Component getTableCellEditorComponent(JTable theTable, Object value,
-            boolean isSelected, int row, int column)
+    public Component getTableCellEditorComponent(JTable theTable,
+            Object value, boolean isSelected, int row, int column)
     {
       currentColor = (FeatureColourI) value;
       this.rowSelected = row;
-      type = me.table.getValueAt(row, TYPE_COLUMN).toString();
+      type = table.getValueAt(row, TYPE_COLUMN).toString();
       button.setOpaque(true);
-      button.setBackground(me.getBackground());
+      button.setBackground(FeatureSettings.this.getBackground());
       if (!currentColor.isSimpleColour())
       {
         JLabel btn = new JLabel();
@@ -1970,14 +2067,14 @@ public class FeatureSettings extends JPanel
 
   /**
    * The cell editor for the Filter column. It displays the text of any filters
-   * for the feature type in that row (in full as a tooltip, possible abbreviated
-   * as display text). On click in the cell, opens the Feature Display Settings
-   * dialog at the Filters tab.
+   * for the feature type in that row (in full as a tooltip, possible
+   * abbreviated as display text). On click in the cell, opens the Feature
+   * Display Settings dialog at the Filters tab.
    */
+  @SuppressWarnings("serial")
   class FilterEditor extends AbstractCellEditor
           implements TableCellEditor, ActionListener
   {
-    FeatureSettings me;
 
     FeatureMatcherSetI currentFilter;
 
@@ -1991,9 +2088,8 @@ public class FeatureSettings extends JPanel
 
     int rowSelected = 0;
 
-    public FilterEditor(FeatureSettings me)
+    public FilterEditor()
     {
-      this.me = me;
       button = new JButton();
       button.setActionCommand(EDIT);
       button.addActionListener(this);
@@ -2008,7 +2104,7 @@ public class FeatureSettings extends JPanel
     {
       if (button == e.getSource())
       {
-        FeatureTypeSettings chooser = new FeatureTypeSettings(me.fr, type);
+        FeatureTypeSettings chooser = new FeatureTypeSettings(fr, type);
         chooser.addActionListener(this);
         chooser.setRequestFocusEnabled(true);
         chooser.requestFocus();
@@ -2030,17 +2126,23 @@ public class FeatureSettings extends JPanel
          * update table data without triggering updateFeatureRenderer
          */
         FeatureColourI currentColor = fr.getFeatureColours().get(type);
-        currentFilter = me.fr.getFeatureFilter(type);
+        currentFilter = fr.getFeatureFilter(type);
         if (currentFilter == null)
         {
           currentFilter = new FeatureMatcherSet();
         }
+
         Object[] data = ((FeatureTableModel) table.getModel())
                 .getData()[rowSelected];
         data[COLOUR_COLUMN] = currentColor;
         data[FILTER_COLUMN] = currentFilter;
         fireEditingStopped();
-        me.table.validate();
+        // SwingJS needs an explicit repaint() here,
+        // rather than relying upon no validation having
+        // occurred since the stopEditing call was made.
+        // Its laying out has not been stopped by the modal frame
+        table.validate();
+        table.repaint();
       }
     }
 
@@ -2051,14 +2153,14 @@ public class FeatureSettings extends JPanel
     }
 
     @Override
-    public Component getTableCellEditorComponent(JTable theTable, Object value,
-            boolean isSelected, int row, int column)
+    public Component getTableCellEditorComponent(JTable theTable,
+            Object value, boolean isSelected, int row, int column)
     {
       currentFilter = (FeatureMatcherSetI) value;
       this.rowSelected = row;
-      type = me.table.getValueAt(row, TYPE_COLUMN).toString();
+      type = table.getValueAt(row, TYPE_COLUMN).toString();
       button.setOpaque(true);
-      button.setBackground(me.getBackground());
+      button.setBackground(FeatureSettings.this.getBackground());
       button.setText(currentFilter.toString());
       button.setIcon(null);
       return button;
@@ -2164,7 +2266,8 @@ class FeatureIcon implements Icon
         g.fillRect(s1, 0, e1 - s1, height);
       }
       g.setColor(gcol.getMaxColour());
-      g.fillRect(0, e1, width - e1, height);
+      // g.fillRect(0, e1, width - e1, height); // BH 2018
+      g.fillRect(e1, 0, width - e1, height);
     }
   }
 }