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;
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;
/*
* 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,
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
*
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;
* save the colour, and repaint stuff
*/
fr.setColour(featureType, acg);
+ refreshFeatureSettings();
ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
updateColoursTab();
@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"));
}
}
/**
* 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);
}
*/
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()
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;
}
* (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();