import jalview.datamodel.GraphLine;
import jalview.datamodel.features.FeatureAttributes;
import jalview.datamodel.features.FeatureAttributes.Datatype;
+import jalview.datamodel.features.FeatureMatcher;
+import jalview.datamodel.features.FeatureMatcherI;
+import jalview.datamodel.features.FeatureMatcherSet;
+import jalview.datamodel.features.FeatureMatcherSetI;
import jalview.schemes.FeatureColour;
import jalview.util.ColorUtils;
import jalview.util.MessageManager;
import jalview.util.matcher.Condition;
-import jalview.util.matcher.KeyedMatcher;
-import jalview.util.matcher.KeyedMatcherI;
-import jalview.util.matcher.KeyedMatcherSet;
-import jalview.util.matcher.KeyedMatcherSetI;
import java.awt.BorderLayout;
import java.awt.Color;
*/
private final FeatureColourI originalColour;
- private final KeyedMatcherSetI originalFilter;
+ private final FeatureMatcherSetI originalFilter;
/*
* set flag to true when setting values programmatically,
*/
private boolean adjusting = false;
+ /*
+ * minimum of the value range for graduated colour
+ * (may be for feature score or for a numeric attribute)
+ */
private float min;
+ /*
+ * maximum of the value range for graduated colour
+ */
private float max;
+ /*
+ * scale factor for conversion between absolute min-max and slider
+ */
private float scaleFactor;
/*
/*
* filters for the currently selected feature type
*/
- private List<KeyedMatcherI> filters;
+ private List<FeatureMatcherI> filters;
// set white normally, black to debug layout
private Color debugBorderColour = Color.white;
* Updates the min-max range if Colour By selected item is Score, or an
* attribute, with a min-max range
*/
- protected void updateMinMax()
+ protected void updateColourMinMax()
{
if (!graduatedColour.isSelected())
{
return;
}
- float[] minMax = null;
String colourBy = (String) colourByRangeCombo.getSelectedItem();
- if (MessageManager.getString("label.score").equals(colourBy))
+ String[] attNames = fromAttributeDisplayName(colourBy);
+ float[] minMax = getMinMax(attNames);
+
+ if (minMax != null)
+ {
+ min = minMax[0];
+ max = minMax[1];
+ }
+ }
+
+ /**
+ * Retrieves the min-max range:
+ * <ul>
+ * <li>of feature score, if colour or filter is by Score</li>
+ * <li>else of the selected attribute</li>
+ * </ul>
+ *
+ * @param attNames
+ * @return
+ */
+ private float[] getMinMax(String[] attNames)
+ {
+ float[] minMax = null;
+ if (MessageManager.getString("label.score").equals(attNames[0]))
{
minMax = fr.getMinMax().get(featureType)[0];
}
else
{
// colour by attribute range
- String[] attNames = fromAttributeDisplayName(colourBy);
minMax = FeatureAttributes.getInstance().getMinMax(featureType,
attNames);
}
-
- if (minMax != null)
- {
- min = minMax[0];
- max = minMax[1];
- }
+ return minMax;
}
/**
* ensure min-max range is for the latest choice of
* 'graduated colour by'
*/
- updateMinMax();
+ updateColourMinMax();
FeatureColourI acg = makeColourFromInputs();
/*
* if this feature type has filters set, load them first
*/
- KeyedMatcherSetI featureFilters = fr.getFeatureFilter(featureType);
+ FeatureMatcherSetI featureFilters = fr.getFeatureFilter(featureType);
if (featureFilters != null)
{
if (!featureFilters.isAnded())
/*
* and an empty filter for the user to populate (add)
*/
- KeyedMatcherI noFilter = new KeyedMatcher(Condition.values()[0], "",
- (String[]) null);
+ FeatureMatcherI noFilter = FeatureMatcher.byLabel(Condition.values()[0],
+ "");
filters.add(noFilter);
/*
* render the conditions in rows, each in its own JPanel
*/
int filterIndex = 0;
- for (KeyedMatcherI filter : filters)
+ for (FeatureMatcherI filter : filters)
{
String[] attName = filter.getKey();
Condition condition = filter.getMatcher().getCondition();
@Override
public void actionPerformed(ActionEvent e)
{
- if (attCombo.getSelectedItem() != null)
+ if (validateFilter(patternField, condCombo))
{
- if (validateFilter(patternField, condCombo))
+ if (updateFilter(attCombo, condCombo, patternField, filterIndex))
{
- updateFilter(attCombo, condCombo, patternField, filterIndex);
filtersChanged();
}
}
* disable pattern field for condition 'Present / NotPresent'
*/
Condition selectedCondition = (Condition) condCombo.getSelectedItem();
- if (selectedCondition == Condition.Present
- || selectedCondition == Condition.NotPresent)
+ if (!selectedCondition.needsAPattern())
{
patternField.setEnabled(false);
}
* if a numeric condition is selected, show the value range
* as a tooltip on the value input field
*/
- if (selectedCondition.isNumeric())
- {
- float[] minMax = FeatureAttributes.getInstance()
- .getMinMax(featureType, attName);
- if (minMax != null)
- {
- String tip = String.format("(%s - %s)",
- DECFMT_2_2.format(minMax[0]), DECFMT_2_2.format(minMax[1]));
- patternField.setToolTipText(tip);
- }
- }
+ updatePatternTooltip(attName, selectedCondition, patternField);
/*
* add remove button if filter is populated (non-empty pattern)
*/
- if (pattern != null && pattern.trim().length() > 0)
+ if (!patternField.isEnabled()
+ || (pattern != null && pattern.trim().length() > 0))
{
// todo: gif for button drawing '-' or 'x'
JButton removeCondition = new BasicArrowButton(SwingConstants.WEST);
}
/**
+ * If a numeric comparison condition is selected, retrieve the min-max range for
+ * the value (score or attribute), and set it as a tooltip on the value file
+ *
+ * @param attName
+ * @param selectedCondition
+ * @param patternField
+ */
+ private void updatePatternTooltip(String[] attName,
+ Condition selectedCondition, JTextField patternField)
+ {
+ patternField.setToolTipText("");
+
+ if (selectedCondition.isNumeric())
+ {
+ float[] minMax = getMinMax(attName);
+ if (minMax != null)
+ {
+ String tip = String.format("(%s - %s)",
+ DECFMT_2_2.format(minMax[0]), DECFMT_2_2.format(minMax[1]));
+ patternField.setToolTipText(tip);
+ }
+ }
+ }
+
+ /**
* Populates the drop-down list of comparison conditions for the given attribute
* name. The conditions added depend on the datatype of the attribute values.
* The supplied condition is set as the selected item in the list, provided it
}
Condition cond = (Condition) condCombo.getSelectedItem();
- if (cond == Condition.Present || cond == Condition.NotPresent)
+ if (cond.needsAPattern())
{
return true;
}
String v1 = value.getText().trim();
if (v1.length() == 0)
{
- return false;
+ // return false;
}
- if (cond.isNumeric())
+ if (cond.isNumeric() && v1.length() > 0)
{
try
{
/**
* Constructs a filter condition from the given input fields, and replaces the
- * condition at filterIndex with the new one
+ * condition at filterIndex with the new one. Does nothing if the pattern field
+ * is blank (unless the match condition is one that doesn't require a pattern,
+ * e.g. 'Is present'). Answers true if the filter was updated, else false.
+ * <p>
+ * This method may update the tooltip on the filter value field to show the
+ * value range, if a numeric condition is selected. This ensures the tooltip is
+ * updated when a numeric valued attribute is chosen on the last 'add a filter'
+ * row.
*
* @param attCombo
* @param condCombo
* @param valueField
* @param filterIndex
*/
- protected void updateFilter(JComboBox<String> attCombo,
+ protected boolean updateFilter(JComboBox<String> attCombo,
JComboBox<Condition> condCombo, JTextField valueField,
int filterIndex)
{
String attName = (String) attCombo.getSelectedItem();
Condition cond = (Condition) condCombo.getSelectedItem();
- String pattern = valueField.getText();
- KeyedMatcherI km = new KeyedMatcher(cond, pattern,
- fromAttributeDisplayName(attName));
+ String pattern = valueField.getText().trim();
+
+ updatePatternTooltip(fromAttributeDisplayName(attName), cond,
+ valueField);
+
+ if (pattern.length() == 0 && cond.needsAPattern())
+ {
+ return false;
+ }
+
+ /*
+ * Construct a matcher that operates on Label, Score,
+ * or named attribute
+ */
+ FeatureMatcherI km = null;
+ if (MessageManager.getString("label.label").equals(attName))
+ {
+ km = FeatureMatcher.byLabel(cond, pattern);
+ }
+ else if (MessageManager.getString("label.score").equals(attName))
+ {
+ km = FeatureMatcher.byScore(cond, pattern);
+ }
+ else
+ {
+ km = FeatureMatcher.byAttribute(cond, pattern,
+ fromAttributeDisplayName(attName));
+ }
filters.set(filterIndex, km);
+
+ return true;
}
/**
* update the filter conditions for the feature type
*/
boolean anded = andFilters.isSelected();
- KeyedMatcherSetI combined = new KeyedMatcherSet();
+ FeatureMatcherSetI combined = new FeatureMatcherSet();
- for (KeyedMatcherI filter : filters)
+ for (FeatureMatcherI filter : filters)
{
String pattern = filter.getMatcher().getPattern();
Condition condition = filter.getMatcher().getCondition();
- if (pattern.trim().length() > 0 || condition == Condition.Present
- || condition == Condition.NotPresent)
+ if (pattern.trim().length() > 0 || !condition.needsAPattern())
{
if (anded)
{