X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FFeatureTypeSettings.java;h=0dd0f1fac020178b4795632409e08fd0fe64a09a;hb=9fcb12165750b20f8a73d0bb976b22be5fda94a2;hp=c784d8d578d7a7ffbcf70da66bf36b68f0756028;hpb=161e8cc8828152180efe8ab861487fea051e4efc;p=jalview.git diff --git a/src/jalview/gui/FeatureTypeSettings.java b/src/jalview/gui/FeatureTypeSettings.java index c784d8d..0dd0f1f 100644 --- a/src/jalview/gui/FeatureTypeSettings.java +++ b/src/jalview/gui/FeatureTypeSettings.java @@ -29,6 +29,8 @@ 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.io.gff.SequenceOntologyI; import jalview.schemes.FeatureColour; import jalview.util.ColorUtils; import jalview.util.MessageManager; @@ -49,7 +51,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; @@ -62,7 +68,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSlider; -import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.border.LineBorder; @@ -107,7 +112,8 @@ public class FeatureTypeSettings extends JalviewDialog /* * FeatureRenderer holds colour scheme and filters for feature types */ - private final FeatureRenderer fr; // todo refactor to allow interface type here + private final FeatureRenderer fr; // todo refactor to allow interface type + // here /* * the view panel to update when settings change @@ -118,10 +124,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 originalColours; - private final FeatureMatcherSetI originalFilter; + private Map originalFilters; /* * set flag to true when setting values programmatically, @@ -155,7 +162,12 @@ public class FeatureTypeSettings extends JalviewDialog private JRadioButton graduatedColour = new JRadioButton(); - private JPanel singleColour = new JPanel(); + /** + * colours and filters are shown in tabbed view or single content pane + */ + JPanel coloursPanel, filtersPanel; + + JPanel singleColour = new JPanel(); private JPanel minColour = new JPanel(); @@ -199,40 +211,55 @@ public class FeatureTypeSettings extends JalviewDialog */ private List filters; - // set white normally, black to debug layout - private Color debugBorderColour = Color.white; - private JPanel chooseFiltersPanel; - private JTabbedPane tabbedPane; + /* + * the root Sequence Ontology terms (if any) that is a parent of + * the current feature type + */ + private String rootSOTerm; - /** - * Constructor - * - * @param frender - * @param theType + /* + * feature types present in Feature Renderer which have the same Sequence + * Ontology root parent as the one this editor is acting on */ - public FeatureTypeSettings(FeatureRenderer frender, String theType) - { - this(frender, false, theType); - } + private final List peerSoTerms; + + /* + * if true, filter or colour settings are also applied to + * any sub-types of rootSOTerm in the Sequence Ontology + */ + private boolean applyFiltersToSubtypes; + + private boolean applyColourToSubtypes; /** - * Constructor, with option to make a blocking dialog (has to complete in the - * AWT event queue thread). Currently this option is always set to false. + * Constructor * * @param frender - * @param blocking * @param theType */ - FeatureTypeSettings(FeatureRenderer frender, boolean blocking, - String theType) + public FeatureTypeSettings(FeatureRenderer frender, String theType) { this.fr = frender; this.featureType = theType; ap = fr.ap; - originalFilter = fr.getFeatureFilter(theType); - originalColour = fr.getFeatureColours().get(theType); + + peerSoTerms = findSequenceOntologyPeers(this.featureType); + + /* + * 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 : peerSoTerms) + { + originalFilters.put(child, fr.getFeatureFilter(child)); + originalColours.put(child, fr.getFeatureColours().get(child)); + } adjusting = true; @@ -256,12 +283,50 @@ public class FeatureTypeSettings extends JalviewDialog String title = MessageManager .formatMessage("label.display_settings_for", new String[] { theType }); - initDialogFrame(this, true, blocking, title, 600, 360); - + initDialogFrame(this, true, false, title, 580, 500); waitForInput(); } /** + * Answers a (possibly empty) list of feature types known to the Feature + * Renderer which share a top level Sequence Ontology parent with the current + * feature type. The current type is not included. + * + * @return + */ + protected List findSequenceOntologyPeers(String featureType) + { + List peers = new ArrayList<>(); + + /* + * first find the SO term (if any) that is the root + * parent of the current type + */ + SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + List roots = so.getRootParents(featureType); + if (roots == null || roots.size() > 1) + { + /* + * feature type is not an SO term, or has ambiguous root + */ + return peers; + } + rootSOTerm = roots.get(0); + + List types = fr.getRenderOrder(); + for (String type : types) + { + if (!type.equals(featureType) && so.isA(type, rootSOTerm)) + { + peers.add(type); + } + + } + Collections.sort(peers); // sort for ease of reading in tooltip + return peers; + } + + /** * Configures the widgets on the Colours tab according to the current feature * colour scheme */ @@ -280,9 +345,9 @@ public class FeatureTypeSettings extends JalviewDialog */ if (fc.isSimpleColour()) { - simpleColour.setSelected(true); singleColour.setBackground(fc.getColour()); singleColour.setForeground(fc.getColour()); + simpleColour.setSelected(true); } /* @@ -325,6 +390,7 @@ public class FeatureTypeSettings extends JalviewDialog * Graduated colour, by score or attribute value range */ graduatedColour.setSelected(true); + updateColourMinMax(); // ensure min, max are set colourByRangeCombo.setEnabled(colourByRangeCombo.getItemCount() > 1); minColour.setEnabled(true); maxColour.setEnabled(true); @@ -379,7 +445,7 @@ public class FeatureTypeSettings extends JalviewDialog : BELOW_THRESHOLD_OPTION); slider.setEnabled(true); slider.setValue((int) (fc.getThreshold() * scaleFactor)); - thresholdValue.setText(String.valueOf(getRoundedSliderValue())); + thresholdValue.setText(String.valueOf(fc.getThreshold())); thresholdValue.setEnabled(true); thresholdIsMin.setEnabled(true); } @@ -402,8 +468,6 @@ public class FeatureTypeSettings extends JalviewDialog private void initialise() { this.setLayout(new BorderLayout()); - tabbedPane = new JTabbedPane(); - this.add(tabbedPane, BorderLayout.CENTER); /* * an ActionListener that applies colour changes @@ -418,18 +482,16 @@ public class FeatureTypeSettings extends JalviewDialog }; /* - * first tab: colour options + * first panel/tab: colour options */ JPanel coloursPanel = initialiseColoursPanel(); - tabbedPane.addTab(MessageManager.getString("action.colour"), - coloursPanel); + this.add(coloursPanel, BorderLayout.NORTH); /* - * second tab: filter options + * second panel/tab: filter options */ JPanel filtersPanel = initialiseFiltersPanel(); - tabbedPane.addTab(MessageManager.getString("label.filters"), - filtersPanel); + this.add(filtersPanel, BorderLayout.CENTER); JPanel okCancelPanel = initialiseOkCancelPanel(); @@ -580,14 +642,21 @@ public class FeatureTypeSettings extends JalviewDialog maxColour.setBorder(new LineBorder(Color.black)); /* - * default max colour to current colour (if a plain colour), - * or to Black if colour by label; make min colour a pale - * version of max colour + * if not set, default max colour to last plain colour, + * and make min colour a pale version of max colour */ - FeatureColourI fc = fr.getFeatureColours().get(featureType); - Color bg = fc.isSimpleColour() ? fc.getColour() : Color.BLACK; - maxColour.setBackground(bg); - minColour.setBackground(ColorUtils.bleachColour(bg, 0.9f)); + FeatureColourI originalColour = originalColours.get(featureType); + Color max = originalColour.getMaxColour(); + if (max == null) + { + max = originalColour.getColour(); + minColour.setBackground(ColorUtils.bleachColour(max, 0.9f)); + } + else + { + maxColour.setBackground(max); + minColour.setBackground(originalColour.getMinColour()); + } noValueCombo = new JComboBox<>(); noValueCombo.addItem(MessageManager.getString("label.no_colour")); @@ -670,6 +739,7 @@ public class FeatureTypeSettings extends JalviewDialog { thresholdValue .setText(String.valueOf(slider.getValue() / scaleFactor)); + thresholdValue.setBackground(Color.white); // to reset red for invalid sliderValueChanged(); } } @@ -735,15 +805,25 @@ public class FeatureTypeSettings extends JalviewDialog private JPanel initialiseColoursPanel() { JPanel colourByPanel = new JPanel(); + colourByPanel.setBackground(Color.white); colourByPanel.setLayout(new BoxLayout(colourByPanel, BoxLayout.Y_AXIS)); + JvSwingUtils.createTitledBorder(colourByPanel, + MessageManager.getString("action.colour"), true); + + /* + * option to apply colour to peer types as well (if there are any) + */ + if (!peerSoTerms.isEmpty()) + { + applyColourToSubtypes = false; + colourByPanel.add(initSubtypesPanel(false)); + } /* * simple colour radio button and colour picker */ JPanel simpleColourPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); simpleColourPanel.setBackground(Color.white); - JvSwingUtils.createTitledBorder(simpleColourPanel, - MessageManager.getString("label.simple"), true); colourByPanel.add(simpleColourPanel); simpleColour = new JRadioButton( @@ -756,15 +836,18 @@ public class FeatureTypeSettings extends JalviewDialog { if (simpleColour.isSelected() && !adjusting) { - showColourChooser(singleColour, "label.select_colour"); + colourChanged(true); } } - }); - + singleColour.setFont(JvSwingUtils.getLabelFont()); singleColour.setBorder(BorderFactory.createLineBorder(Color.black)); singleColour.setPreferredSize(new Dimension(40, 20)); + FeatureColourI originalColour = originalColours.get(featureType); + singleColour.setBackground(originalColour.getColour()); + singleColour.setForeground(originalColour.getColour()); + singleColour.addMouseListener(new MouseAdapter() { @Override @@ -834,6 +917,46 @@ public class FeatureTypeSettings extends JalviewDialog return colourByPanel; } + /** + * Constructs and returns a panel with a checkbox for the option to apply any + * changes also to sub-types of the feature type + * + * @return + */ + protected JPanel initSubtypesPanel(final boolean forFilters) + { + JPanel toSubtypes = new JPanel(new FlowLayout(FlowLayout.LEFT)); + toSubtypes.setBackground(Color.WHITE); + JCheckBox applyToSubtypesCB = new JCheckBox(MessageManager + .formatMessage("label.apply_to_subtypes", rootSOTerm)); + applyToSubtypesCB.setToolTipText(getSubtypesTooltip()); + applyToSubtypesCB.addActionListener(new ActionListener() + { + /* + * reset and reapply settings on toggle of checkbox + */ + @Override + public void actionPerformed(ActionEvent e) + { + if (forFilters) + { + applyFiltersToSubtypes = applyToSubtypesCB.isSelected(); + restoreOriginalFilters(); + filtersChanged(); + } + else + { + applyColourToSubtypes = applyToSubtypesCB.isSelected(); + restoreOriginalColours(); + colourChanged(true); + } + } + }); + toSubtypes.add(applyToSubtypesCB); + + return toSubtypes; + } + private void showColourChooser(JPanel colourPanel, String key) { Color col = JColorChooser.showDialog(this, @@ -848,9 +971,9 @@ public class FeatureTypeSettings extends JalviewDialog } /** - * Constructs and sets the selected colour options as the colour for the feature - * type, and repaints the alignment, and optionally the Overview and/or - * structure viewer if open + * Constructs and sets the selected colour options as the colour for the + * feature type, and repaints the alignment, and optionally the Overview + * and/or structure viewer if open * * @param updateStructsAndOverview */ @@ -873,9 +996,17 @@ public class FeatureTypeSettings extends JalviewDialog FeatureColourI acg = makeColourFromInputs(); /* - * save the colour, and repaint stuff + * save the colour, and set on subtypes if selected */ fr.setColour(featureType, acg); + if (applyColourToSubtypes) + { + for (String child : peerSoTerms) + { + fr.setColour(child, acg); + } + } + refreshFeatureSettings(); ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview); updateColoursTab(); @@ -889,42 +1020,9 @@ public class FeatureTypeSettings extends JalviewDialog private FeatureColourI makeColourFromInputs() { /* - * easiest case - a single colour - */ - if (simpleColour.isSelected()) - { - return new FeatureColour(singleColour.getBackground()); - } - - /* - * next easiest case - colour by Label, or attribute text - */ - if (byCategory.isSelected()) - { - Color c = this.getBackground(); - FeatureColourI fc = new FeatureColour(c, c, null, 0f, 0f); - fc.setColourByLabel(true); - String byWhat = (String) colourByTextCombo.getSelectedItem(); - if (!LABEL_18N.equals(byWhat)) - { - fc.setAttributeName( - FeatureMatcher.fromAttributeDisplayName(byWhat)); - } - return fc; - } - - /* - * remaining case - graduated colour by score, or attribute value + * min-max range is to (or from) threshold value if + * 'threshold is min/max' is selected */ - Color noColour = null; - if (noValueCombo.getSelectedIndex() == MIN_COLOUR_OPTION) - { - noColour = minColour.getBackground(); - } - else if (noValueCombo.getSelectedIndex() == MAX_COLOUR_OPTION) - { - noColour = maxColour.getBackground(); - } float thresh = 0f; try @@ -934,11 +1032,6 @@ public class FeatureTypeSettings extends JalviewDialog { // invalid inputs are already handled on entry } - - /* - * min-max range is to (or from) threshold value if - * 'threshold is min/max' is selected - */ float minValue = min; float maxValue = max; final int thresholdOption = threshold.getSelectedIndex(); @@ -952,14 +1045,50 @@ public class FeatureTypeSettings extends JalviewDialog { maxValue = thresh; } + Color noColour = null; + if (noValueCombo.getSelectedIndex() == MIN_COLOUR_OPTION) + { + noColour = minColour.getBackground(); + } + else if (noValueCombo.getSelectedIndex() == MAX_COLOUR_OPTION) + { + noColour = maxColour.getBackground(); + } /* - * make the graduated colour + * construct a colour that 'remembers' all the options, including + * those not currently selected */ - FeatureColourI fc = new FeatureColour(minColour.getBackground(), - maxColour.getBackground(), noColour, minValue, maxValue); + FeatureColourI fc = new FeatureColour(singleColour.getBackground(), + minColour.getBackground(), maxColour.getBackground(), noColour, + minValue, maxValue); /* + * easiest case - a single colour + */ + if (simpleColour.isSelected()) + { + ((FeatureColour) fc).setGraduatedColour(false); + return fc; + } + + /* + * next easiest case - colour by Label, or attribute text + */ + if (byCategory.isSelected()) + { + fc.setColourByLabel(true); + String byWhat = (String) colourByTextCombo.getSelectedItem(); + if (!LABEL_18N.equals(byWhat)) + { + fc.setAttributeName( + FeatureMatcher.fromAttributeDisplayName(byWhat)); + } + return fc; + } + + /* + * remaining case - graduated colour by score, or attribute value; * set attribute to colour by if selected */ String byWhat = (String) colourByRangeCombo.getSelectedItem(); @@ -993,9 +1122,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")); } } @@ -1010,16 +1144,34 @@ 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); + restoreOriginalColours(); + restoreOriginalFilters(); ap.paintAlignment(true, true); } + protected void restoreOriginalFilters() + { + for (Entry entry : originalFilters + .entrySet()) + { + fr.setFeatureFilter(entry.getKey(), entry.getValue()); + } + } + + protected void restoreOriginalColours() + { + for (Entry entry : originalColours.entrySet()) + { + fr.setColour(entry.getKey(), entry.getValue()); + } + } + /** * Action on text entry of a threshold value */ @@ -1027,21 +1179,23 @@ public class FeatureTypeSettings extends JalviewDialog { try { + /* + * set 'adjusting' flag while moving the slider, so it + * doesn't then in turn change the value (with rounding) + */ adjusting = true; float f = Float.parseFloat(thresholdValue.getText()); + f = Float.max(f, this.min); + f = Float.min(f, this.max); + thresholdValue.setText(String.valueOf(f)); slider.setValue((int) (f * scaleFactor)); threshline.value = f; thresholdValue.setBackground(Color.white); // ok - - /* - * force repaint of any Overview window or structure - */ - ap.paintAlignment(true, true); + adjusting = false; + colourChanged(true); } catch (NumberFormatException ex) { thresholdValue.setBackground(Color.red); // not ok - } finally - { adjusting = false; } } @@ -1064,8 +1218,8 @@ public class FeatureTypeSettings extends JalviewDialog /** * Converts the slider value to its absolute value by dividing by the - * scaleFactor. Rounding errors are squashed by forcing min/max of slider range - * to the actual min/max of feature score range + * scaleFactor. Rounding errors are squashed by forcing min/max of slider + * range to the actual min/max of feature score range * * @return */ @@ -1088,11 +1242,11 @@ public class FeatureTypeSettings extends JalviewDialog } /** - * A helper method to build the drop-down choice of attributes for a feature. If - * 'withRange' is true, then Score, and any attributes with a min-max range, are - * added. If 'withText' is true, Label and any known attributes are added. This - * allows 'categorical numerical' attributes e.g. codon position to be coloured - * by text. + * A helper method to build the drop-down choice of attributes for a feature. + * If 'withRange' is true, then Score, and any attributes with a min-max + * range, are added. If 'withText' is true, Label and any known attributes are + * added. This allows 'categorical numerical' attributes e.g. codon position + * to be coloured by text. *

* Where metadata is available with a description for an attribute, that is * added as a tooltip. @@ -1158,11 +1312,25 @@ public class FeatureTypeSettings extends JalviewDialog { filters = new ArrayList<>(); + JPanel outerPanel = new JPanel(); + outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS)); + outerPanel.setBackground(Color.white); + + /* + * option to apply colour to peer types as well (if there are any) + */ + if (!peerSoTerms.isEmpty()) + { + applyFiltersToSubtypes = false; + outerPanel.add(initSubtypesPanel(true)); + } + JPanel filtersPanel = new JPanel(); filtersPanel.setLayout(new BoxLayout(filtersPanel, BoxLayout.Y_AXIS)); filtersPanel.setBackground(Color.white); JvSwingUtils.createTitledBorder(filtersPanel, MessageManager.getString("label.filters"), true); + outerPanel.add(filtersPanel); JPanel andOrPanel = initialiseAndOrPanel(); filtersPanel.add(andOrPanel); @@ -1175,7 +1343,7 @@ public class FeatureTypeSettings extends JalviewDialog chooseFiltersPanel.setBackground(Color.white); filtersPanel.add(chooseFiltersPanel); - return filtersPanel; + return outerPanel; } /** @@ -1185,9 +1353,9 @@ 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)); + andFilters = new JRadioButton(MessageManager.getString("label.and")); orFilters = new JRadioButton(MessageManager.getString("label.or")); ActionListener actionListener = new ActionListener() @@ -1208,10 +1376,29 @@ public class FeatureTypeSettings extends JalviewDialog new JLabel(MessageManager.getString("label.join_conditions"))); andOrPanel.add(andFilters); andOrPanel.add(orFilters); + return andOrPanel; } /** + * Builds a tooltip for the 'Apply to subtypes' checkbox with a list of + * subtypes of this feature type + * + * @return + */ + protected String getSubtypesTooltip() + { + StringBuilder sb = new StringBuilder(20 * peerSoTerms.size()); + sb.append(MessageManager.getString("label.apply_also_to")); + for (String child : peerSoTerms) + { + sb.append("
").append(child); + } + String tooltip = JvSwingUtils.wrapTooltip(true, sb.toString()); + return tooltip; + } + + /** * Refreshes the display to show any filters currently configured for the * selected feature type (editable, with 'remove' option), plus one extra row * for adding a condition. This should be called after a filter has been @@ -1270,7 +1457,6 @@ public class FeatureTypeSettings extends JalviewDialog for (FeatureMatcherI filter : filters) { JPanel row = addFilter(filter, attNames, filterIndex); - row.setBorder(BorderFactory.createLineBorder(debugBorderColour)); chooseFiltersPanel.add(row); filterIndex++; } @@ -1282,7 +1468,8 @@ public class FeatureTypeSettings extends JalviewDialog /** * A helper method that constructs a row (panel) with one filter condition: *

    - *
  • a drop-down list of Label, Score and attribute names to choose from
  • + *
  • a drop-down list of Label, Score and attribute names to choose + * from
  • *
  • a drop-down list of conditions to choose from
  • *
  • a text field for input of a match pattern
  • *
  • optionally, a 'remove' button
  • @@ -1407,16 +1594,13 @@ public class FeatureTypeSettings extends JalviewDialog * disable pattern field for condition 'Present / NotPresent' */ Condition selectedCondition = (Condition) condCombo.getSelectedItem(); - if (!selectedCondition.needsAPattern()) - { - patternField.setEnabled(false); - } + patternField.setEnabled(selectedCondition.needsAPattern()); /* * if a numeric condition is selected, show the value range * as a tooltip on the value input field */ - setPatternTooltip(filterBy, selectedCondition, patternField); + setNumericHints(filterBy, selectedCondition, patternField); /* * add remove button if filter is populated (non-empty pattern) @@ -1471,15 +1655,20 @@ public class FeatureTypeSettings extends JalviewDialog } /** - * 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 + * If a numeric comparison condition is selected, retrieves the min-max range + * for the value (score or attribute), and sets it as a tooltip on the value + * field. If the field is currently empty, then pre-populates it with + *
      + *
    • the minimum value, if condition is > or >=
    • + *
    • the maximum value, if condition is < or <=
    • + *
    * * @param attName * @param selectedCondition * @param patternField */ - private void setPatternTooltip(String attName, - Condition selectedCondition, JTextField patternField) + private void setNumericHints(String attName, Condition selectedCondition, + JTextField patternField) { patternField.setToolTipText(""); @@ -1488,19 +1677,36 @@ public class FeatureTypeSettings extends JalviewDialog 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])); + String minFormatted = DECFMT_2_2.format(minMax[0]); + String maxFormatted = DECFMT_2_2.format(minMax[1]); + String tip = String.format("(%s - %s)", minFormatted, maxFormatted); patternField.setToolTipText(tip); + if (patternField.getText().isEmpty()) + { + if (selectedCondition == Condition.GE + || selectedCondition == Condition.GT) + { + patternField.setText(minFormatted); + } + else + { + if (selectedCondition == Condition.LE + || selectedCondition == Condition.LT) + { + patternField.setText(maxFormatted); + } + } + } } } } /** - * 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 - * is in the list. If the pattern is now invalid (non-numeric pattern for a - * numeric condition), it is cleared. + * 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 is in the list. If the pattern is now invalid + * (non-numeric pattern for a numeric condition), it is cleared. * * @param attName * @param cond @@ -1527,10 +1733,11 @@ public class FeatureTypeSettings extends JalviewDialog ItemListener listener = condCombo.getItemListeners()[0]; condCombo.removeItemListener(listener); boolean condIsValid = false; + condCombo.removeAllItems(); for (Condition c : Condition.values()) { - if ((c.isNumeric() && type != Datatype.Character) + if ((c.isNumeric() && type == Datatype.Number) || (!c.isNumeric() && type != Datatype.Number)) { condCombo.addItem(c); @@ -1553,8 +1760,6 @@ public class FeatureTypeSettings extends JalviewDialog condCombo.setSelectedIndex(0); } - condCombo.addItemListener(listener); - /* * clear pattern if it is now invalid for condition */ @@ -1572,15 +1777,20 @@ public class FeatureTypeSettings extends JalviewDialog patternField.setText(""); } } + + /* + * restore the listener + */ + condCombo.addItemListener(listener); } /** - * Answers true unless a numeric condition has been selected with a non-numeric - * value. Sets the value field to RED with a tooltip if in error. + * Answers true unless a numeric condition has been selected with a + * non-numeric value. Sets the value field to RED with a tooltip if in error. *

    - * If the pattern is expected but is empty, this method returns false, but does - * not mark the field as invalid. This supports selecting an attribute for a new - * condition before a match pattern has been entered. + * If the pattern is expected but is empty, this method returns false, but + * does not mark the field as invalid. This supports selecting an attribute + * for a new condition before a match pattern has been entered. * * @param value * @param condCombo @@ -1626,14 +1836,15 @@ public class FeatureTypeSettings extends JalviewDialog /** * Constructs a filter condition from the given input fields, and replaces the - * 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. + * 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. *

    * 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. + * 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 @@ -1648,10 +1859,11 @@ public class FeatureTypeSettings extends JalviewDialog Condition cond = (Condition) condCombo.getSelectedItem(); String pattern = valueField.getText().trim(); - setPatternTooltip(attName, cond, valueField); + setNumericHints(attName, cond, valueField); if (pattern.length() == 0 && cond.needsAPattern()) { + valueField.setEnabled(true); // ensure pattern field is enabled! return false; } @@ -1680,17 +1892,6 @@ public class FeatureTypeSettings extends JalviewDialog } /** - * Makes the dialog visible, at the Feature Colour tab or at the Filters tab - * - * @param coloursTab - */ - public void showTab(boolean coloursTab) - { - setVisible(true); - tabbedPane.setSelectedIndex(coloursTab ? 0 : 1); - } - - /** * Action on any change to feature filtering, namely *

      *
    • change of selected attribute
    • @@ -1698,8 +1899,8 @@ public class FeatureTypeSettings extends JalviewDialog *
    • change of match pattern
    • *
    • removal of a condition
    • *
    - * The inputs are parsed into a combined filter and this is set for the feature - * type, and the alignment redrawn. + * The inputs are parsed into a combined filter and this is set for the + * feature type, and the alignment redrawn. */ protected void filtersChanged() { @@ -1731,6 +1932,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) + { + for (String child : peerSoTerms) + { + fr.setFeatureFilter(child, combined.isEmpty() ? null : combined); + } + } + + refreshFeatureSettings(); ap.paintAlignment(true, true); updateFiltersTab();