JAL-3010 options to hide / apply changes to ontology sub-types
[jalview.git] / src / jalview / gui / FeatureTypeSettings.java
index e13f6ee..64b5c8c 100644 (file)
@@ -29,6 +29,7 @@ import jalview.datamodel.features.FeatureMatcher;
 import jalview.datamodel.features.FeatureMatcherI;
 import jalview.datamodel.features.FeatureMatcherSet;
 import jalview.datamodel.features.FeatureMatcherSetI;
+import jalview.io.gff.SequenceOntologyFactory;
 import jalview.schemes.FeatureColour;
 import jalview.util.ColorUtils;
 import jalview.util.MessageManager;
@@ -49,7 +50,11 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
@@ -118,10 +123,11 @@ public class FeatureTypeSettings extends JalviewDialog
 
   /*
    * the colour and filters to reset to on Cancel
+   * (including feature sub-types if modified)
    */
-  private final FeatureColourI originalColour;
+  private Map<String, FeatureColourI> originalColours;
 
-  private final FeatureMatcherSetI originalFilter;
+  private Map<String, FeatureMatcherSetI> originalFilters;
 
   /*
    * set flag to true when setting values programmatically,
@@ -206,6 +212,24 @@ public class FeatureTypeSettings extends JalviewDialog
 
   private JTabbedPane tabbedPane;
 
+  /*
+   * feature types present in Feature Renderer which are
+   * sub-types of the one this editor is acting on
+   */
+  private final List<String> subTypes;
+
+  /*
+   * if selected, filter settings are also applied to any 
+   * feature sub-types in the Sequence Ontology
+   */
+  private JCheckBox applyFiltersToSubtypes;
+
+  /*
+   * if selected, colour settings are also applied to any 
+   * feature sub-types in the Sequence Ontology
+   */
+  private JCheckBox applyColourToChildren;
+
   /**
    * Constructor
    * 
@@ -231,8 +255,27 @@ public class FeatureTypeSettings extends JalviewDialog
     this.fr = frender;
     this.featureType = theType;
     ap = fr.ap;
-    originalFilter = fr.getFeatureFilter(theType);
-    originalColour = fr.getFeatureColours().get(theType);
+
+    /*
+     * determine sub-types (if any) of this feature type
+     */
+    List<String> types = fr.getRenderOrder();
+    subTypes = Collections.unmodifiableList(SequenceOntologyFactory
+            .getInstance().getChildTerms(this.featureType, types));
+
+    /*
+     * save original colours and filters for this feature type
+     * and any sub-types, to restore on Cancel
+     */
+    originalFilters = new HashMap<>();
+    originalFilters.put(theType, fr.getFeatureFilter(theType));
+    originalColours = new HashMap<>();
+    originalColours.put(theType, fr.getFeatureColours().get(theType));
+    for (String child : subTypes)
+    {
+      originalFilters.put(child, fr.getFeatureFilter(child));
+      originalColours.put(child, fr.getFeatureColours().get(child));
+    }
 
     adjusting = true;
 
@@ -877,6 +920,7 @@ public class FeatureTypeSettings extends JalviewDialog
      * save the colour, and repaint stuff
      */
     fr.setColour(featureType, acg);
+    refreshFeatureSettings();
     ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
 
     updateColoursTab();
@@ -994,9 +1038,14 @@ public class FeatureTypeSettings extends JalviewDialog
   @Override
   protected void raiseClosed()
   {
+    refreshFeatureSettings();
+  }
+
+  protected void refreshFeatureSettings()
+  {
     if (this.featureSettings != null)
     {
-      featureSettings.actionPerformed(new ActionEvent(this, 0, "CLOSED"));
+      featureSettings.actionPerformed(new ActionEvent(this, 0, "REFRESH"));
     }
   }
 
@@ -1011,13 +1060,22 @@ public class FeatureTypeSettings extends JalviewDialog
 
   /**
    * Action on Cancel is to restore colour scheme and filters as they were when
-   * the dialog was opened
+   * the dialog was opened (including any feature sub-types that may have been
+   * changed)
    */
   @Override
   public void cancelPressed()
   {
-    fr.setColour(featureType, originalColour);
-    fr.setFeatureFilter(featureType, originalFilter);
+    for (Entry<String, FeatureColourI> entry : originalColours.entrySet())
+    {
+      fr.setColour(entry.getKey(), entry.getValue());
+    }
+    for (Entry<String, FeatureMatcherSetI> entry : originalFilters
+            .entrySet())
+    {
+      fr.setFeatureFilter(entry.getKey(), entry.getValue());
+    }
+
     ap.paintAlignment(true, true);
   }
 
@@ -1186,9 +1244,12 @@ public class FeatureTypeSettings extends JalviewDialog
    */
   private JPanel initialiseAndOrPanel()
   {
-    JPanel andOrPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    JPanel andOrPanel = new JPanel(new BorderLayout());
     andOrPanel.setBackground(Color.white);
-    andOrPanel.setBorder(BorderFactory.createLineBorder(debugBorderColour));
+    JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    andOrPanel.add(panel1, BorderLayout.WEST);
+    panel1.setBackground(Color.white);
+    panel1.setBorder(BorderFactory.createLineBorder(debugBorderColour));
     andFilters = new JRadioButton(MessageManager.getString("label.and"));
     orFilters = new JRadioButton(MessageManager.getString("label.or"));
     ActionListener actionListener = new ActionListener()
@@ -1205,10 +1266,32 @@ public class FeatureTypeSettings extends JalviewDialog
     andOr.add(andFilters);
     andOr.add(orFilters);
     andFilters.setSelected(true);
-    andOrPanel.add(
+    panel1.add(
             new JLabel(MessageManager.getString("label.join_conditions")));
-    andOrPanel.add(andFilters);
-    andOrPanel.add(orFilters);
+    panel1.add(andFilters);
+    panel1.add(orFilters);
+
+    /*
+     * add an 'Apply to child terms' checkbox if there are any child terms
+     */
+    applyFiltersToSubtypes = new JCheckBox("Apply also to child terms");
+    if (!subTypes.isEmpty())
+    {
+      JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+      panel2.setBackground(Color.white);
+      andOrPanel.add(panel2, BorderLayout.EAST);
+      StringBuilder sb = new StringBuilder(20 * subTypes.size());
+      sb.append("Apply filters also to child terms" + ":"); // todo i18n
+      Collections.sort(subTypes);
+      for (String child : subTypes)
+      {
+        sb.append("<br>").append(child);
+      }
+      String tooltip = JvSwingUtils.wrapTooltip(true, sb.toString());
+      applyFiltersToSubtypes.setToolTipText(tooltip);
+      panel2.add(applyFiltersToSubtypes);
+    }
+
     return andOrPanel;
   }
 
@@ -1756,6 +1839,15 @@ public class FeatureTypeSettings extends JalviewDialog
      * (note this might now be an empty filter with no conditions)
      */
     fr.setFeatureFilter(featureType, combined.isEmpty() ? null : combined);
+    if (applyFiltersToSubtypes.isSelected())
+    {
+      for (String child : subTypes)
+      {
+        fr.setFeatureFilter(child, combined.isEmpty() ? null : combined);
+      }
+    }
+
+    refreshFeatureSettings();
     ap.paintAlignment(true, true);
 
     updateFiltersTab();