From: Jim Procter Date: Mon, 3 Aug 2020 09:40:46 +0000 (+0100) Subject: Merge branch 'bug/JAL-2983negativeSliderMin' into develop X-Git-Tag: Develop-2_11_2_0-d20201215~24^2~21 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=4160e6f1fa6aa45849153cce5794faa93e3a19c4;hp=033962da90469745dd6639a1346ecbcbe2ed071f;p=jalview.git Merge branch 'bug/JAL-2983negativeSliderMin' into develop Conflicts: src/jalview/gui/FeatureSettings.java src/jalview/gui/FeatureTypeSettings.java --- diff --git a/src/jalview/gui/AnnotationColourChooser.java b/src/jalview/gui/AnnotationColourChooser.java index e89c1c2..ad013f5 100644 --- a/src/jalview/gui/AnnotationColourChooser.java +++ b/src/jalview/gui/AnnotationColourChooser.java @@ -53,8 +53,6 @@ import net.miginfocom.swing.MigLayout; @SuppressWarnings("serial") public class AnnotationColourChooser extends AnnotationRowFilter { - private static final int ONETHOUSAND = 1000; - private ColourSchemeI oldcs; private JButton defColours; @@ -147,7 +145,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter "error.implementation_error_dont_know_about_threshold_setting")); } thresholdIsMin.setSelected(acg.isThresholdIsMinMax()); - thresholdValue.setText("" + acg.getAnnotationThreshold()); + thresholdValue + .setText(String.valueOf(acg.getAnnotationThreshold())); } jbInit(); @@ -329,7 +328,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter { updateView(); } - getCurrentAnnotation().threshold.value = slider.getValue() / 1000f; + getCurrentAnnotation().threshold.value = getSliderValue(); propagateSeqAssociatedThreshold(updateAllAnnotation, getCurrentAnnotation()); ap.paintAlignment(false, false); @@ -369,6 +368,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter thresholdValue.setEnabled(true); thresholdIsMin.setEnabled(!useOriginalColours.isSelected()); + final AlignmentAnnotation currentAnnotation = getCurrentAnnotation(); if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD) { slider.setEnabled(false); @@ -377,33 +377,26 @@ public class AnnotationColourChooser extends AnnotationRowFilter thresholdIsMin.setEnabled(false); } else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD - && getCurrentAnnotation().threshold == null) + && currentAnnotation.threshold == null) { - getCurrentAnnotation().setThreshold(new GraphLine( - (getCurrentAnnotation().graphMax - - getCurrentAnnotation().graphMin) / 2f, + currentAnnotation.setThreshold(new GraphLine( + (currentAnnotation.graphMax - currentAnnotation.graphMin) + / 2f, "Threshold", Color.black)); } if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD) { adjusting = true; - float range = getCurrentAnnotation().graphMax * ONETHOUSAND - - getCurrentAnnotation().graphMin * ONETHOUSAND; - - slider.setMinimum( - (int) (getCurrentAnnotation().graphMin * ONETHOUSAND)); - slider.setMaximum( - (int) (getCurrentAnnotation().graphMax * ONETHOUSAND)); - slider.setValue( - (int) (getCurrentAnnotation().threshold.value * ONETHOUSAND)); - thresholdValue.setText(getCurrentAnnotation().threshold.value + ""); - slider.setMajorTickSpacing((int) (range / 10f)); + setSliderModel(currentAnnotation.graphMin, currentAnnotation.graphMax, + currentAnnotation.threshold.value); slider.setEnabled(true); + + setThresholdValueText(); thresholdValue.setEnabled(true); adjusting = false; } - colorAlignmentContaining(getCurrentAnnotation(), selectedThresholdItem); + colorAlignmentContaining(currentAnnotation, selectedThresholdItem); ap.alignmentChanged(); } diff --git a/src/jalview/gui/AnnotationColumnChooser.java b/src/jalview/gui/AnnotationColumnChooser.java index fbc93b5..589f4bd 100644 --- a/src/jalview/gui/AnnotationColumnChooser.java +++ b/src/jalview/gui/AnnotationColumnChooser.java @@ -21,6 +21,7 @@ package jalview.gui; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.HiddenColumns; import jalview.io.cache.JvCacheableInputBox; import jalview.schemes.AnnotationColourGradient; @@ -255,7 +256,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter { if (slider.isEnabled()) { - getCurrentAnnotation().threshold.value = slider.getValue() / 1000f; + getCurrentAnnotation().threshold.value = getSliderValue(); updateView(); propagateSeqAssociatedThreshold(updateAllAnnotation, getCurrentAnnotation()); @@ -285,6 +286,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter thresholdValue.setEnabled(true); percentThreshold.setEnabled(true); + final AlignmentAnnotation currentAnnotation = getCurrentAnnotation(); if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD) { slider.setEnabled(false); @@ -295,26 +297,22 @@ public class AnnotationColumnChooser extends AnnotationRowFilter } else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD) { - if (getCurrentAnnotation().threshold == null) + if (currentAnnotation.threshold == null) { - getCurrentAnnotation().setThreshold(new jalview.datamodel.GraphLine( - (getCurrentAnnotation().graphMax - - getCurrentAnnotation().graphMin) / 2f, + currentAnnotation.setThreshold(new jalview.datamodel.GraphLine( + (currentAnnotation.graphMax + - currentAnnotation.graphMin) / 2f, "Threshold", Color.black)); } adjusting = true; - float range = getCurrentAnnotation().graphMax * 1000 - - getCurrentAnnotation().graphMin * 1000; - slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000)); - slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000)); - slider.setValue( - (int) (getCurrentAnnotation().threshold.value * 1000)); + setSliderModel(currentAnnotation.graphMin, + currentAnnotation.graphMax, + currentAnnotation.threshold.value); setThresholdValueText(); - slider.setMajorTickSpacing((int) (range / 10f)); slider.setEnabled(true); thresholdValue.setEnabled(true); adjusting = false; @@ -322,10 +320,10 @@ public class AnnotationColumnChooser extends AnnotationRowFilter // build filter params filterParams.setThresholdType( AnnotationFilterParameter.ThresholdType.NO_THRESHOLD); - if (getCurrentAnnotation().isQuantitative()) + if (currentAnnotation.isQuantitative()) { filterParams - .setThresholdValue(getCurrentAnnotation().threshold.value); + .setThresholdValue(currentAnnotation.threshold.value); if (selectedThresholdItem == AnnotationColourGradient.ABOVE_THRESHOLD) { @@ -381,7 +379,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter // adding them to the selection av.showAllHiddenColumns(); av.getColumnSelection().filterAnnotations( - getCurrentAnnotation().annotations, filterParams); + currentAnnotation.annotations, filterParams); boolean hideCols = getActionOption() == ACTION_OPTION_HIDE; if (hideCols) diff --git a/src/jalview/gui/AnnotationRowFilter.java b/src/jalview/gui/AnnotationRowFilter.java index f13cb10..6f72e10 100644 --- a/src/jalview/gui/AnnotationRowFilter.java +++ b/src/jalview/gui/AnnotationRowFilter.java @@ -35,6 +35,8 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.math.BigDecimal; +import java.math.MathContext; import java.util.HashMap; import java.util.Map; import java.util.Vector; @@ -44,7 +46,6 @@ import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JInternalFrame; import javax.swing.JPanel; -import javax.swing.JSlider; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -52,6 +53,10 @@ import javax.swing.event.ChangeListener; @SuppressWarnings("serial") public abstract class AnnotationRowFilter extends JPanel { + private static final String TWO_DP = "%.2f"; + + private final static MathContext FOUR_SIG_FIG = new MathContext(4); + protected AlignViewport av; protected AlignmentPanel ap; @@ -64,7 +69,7 @@ public abstract class AnnotationRowFilter extends JPanel protected JCheckBox percentThreshold = new JCheckBox(); - protected JSlider slider = new JSlider(); + protected Slider slider; protected JTextField thresholdValue = new JTextField(20); @@ -103,6 +108,8 @@ public abstract class AnnotationRowFilter extends JPanel { this.av = viewport; this.ap = alignPanel; + this.slider = new Slider(0f, 100f, 50f); + thresholdValue.addFocusListener(new FocusAdapter() { @Override @@ -140,16 +147,62 @@ public abstract class AnnotationRowFilter extends JPanel adjusting = true; if (percentThreshold.isSelected()) { - thresholdValue.setText("" + (slider.getValue() - slider.getMinimum()) - * 100f / (slider.getMaximum() - slider.getMinimum())); + thresholdValue + .setText(String.format(TWO_DP, getSliderPercentageValue())); } else { - thresholdValue.setText((slider.getValue() / 1000f) + ""); + /* + * round to 4 significant digits without trailing zeroes + */ + float f = getSliderValue(); + BigDecimal formatted = new BigDecimal(f).round(FOUR_SIG_FIG) + .stripTrailingZeros(); + thresholdValue.setText(formatted.toPlainString()); } adjusting = oldadj; } + /** + * Answers the value of the slider position (descaled to 'true' value) + * + * @return + */ + protected float getSliderValue() + { + return slider.getSliderValue(); + } + + /** + * Sets the slider value (scaled from the true value to the slider range) + * + * @param value + */ + protected void setSliderValue(float value) + { + slider.setSliderValue(value); + } + /** + * Answers the value of the slider position as a percentage between minimum and + * maximum of its range + * + * @return + */ + protected float getSliderPercentageValue() + { + return slider.getSliderPercentageValue(); + } + + /** + * Sets the slider position for a given percentage value of its min-max range + * + * @param pct + */ + protected void setSliderPercentageValue(float pct) + { + slider.setSliderPercentageValue(pct); + } + protected void addSliderMouseListeners() { @@ -290,6 +343,10 @@ public abstract class AnnotationRowFilter extends JPanel updateView(); } + /** + * Updates the slider position, and the display, for an update in the slider's + * text input field + */ protected void thresholdValue_actionPerformed() { try @@ -297,12 +354,11 @@ public abstract class AnnotationRowFilter extends JPanel float f = Float.parseFloat(thresholdValue.getText()); if (percentThreshold.isSelected()) { - slider.setValue(slider.getMinimum() + ((int) ((f / 100f) - * (slider.getMaximum() - slider.getMinimum())))); + setSliderPercentageValue(f); } else { - slider.setValue((int) (f * 1000)); + setSliderValue(f); } updateView(); } catch (NumberFormatException ex) @@ -528,4 +584,23 @@ public abstract class AnnotationRowFilter extends JPanel valueChanged(true); } } + + /** + * Sets the min-max range and current value of the slider, with rescaling from + * true values to slider range as required + * + * @param min + * @param max + * @param value + */ + protected void setSliderModel(float min, float max, float value) + { + slider.setSliderModel(min, max, value); + + /* + * tick mark every 10th position + */ + slider.setMajorTickSpacing( + (slider.getMaximum() - slider.getMinimum()) / 10); + } } diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index b49593a..e636455 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -150,7 +150,7 @@ public class FeatureSettings extends JPanel */ Object[][] originalData; - float originalTransparency; + private float originalTransparency; private ViewStyleI originalViewStyle; @@ -182,7 +182,7 @@ public class FeatureSettings extends JPanel /* * true when Feature Settings are updating from feature renderer */ - boolean handlingUpdate = false; + private boolean handlingUpdate = false; /* * a change listener to ensure the dialog is updated if diff --git a/src/jalview/gui/FeatureTypeSettings.java b/src/jalview/gui/FeatureTypeSettings.java index 200911d..54eeba7 100644 --- a/src/jalview/gui/FeatureTypeSettings.java +++ b/src/jalview/gui/FeatureTypeSettings.java @@ -50,6 +50,8 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.math.BigDecimal; +import java.math.MathContext; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -63,7 +65,6 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; -import javax.swing.JSlider; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; @@ -79,6 +80,8 @@ import javax.swing.event.ChangeListener; */ public class FeatureTypeSettings extends JalviewDialog { + private final static MathContext FOUR_SIG_FIG = new MathContext(4); + private final static String LABEL_18N = MessageManager .getString("label.label"); @@ -142,11 +145,6 @@ public class FeatureTypeSettings extends JalviewDialog private float max; /* - * scale factor for conversion between absolute min-max and slider - */ - float scaleFactor; - - /* * radio button group, to select what to colour by: * simple colour, by category (text), or graduated */ @@ -168,7 +166,7 @@ public class FeatureTypeSettings extends JalviewDialog private JComboBox threshold = new JComboBox<>(); - JSlider slider = new JSlider(); + private Slider slider; JTextField thresholdValue = new JTextField(20); @@ -347,12 +345,11 @@ public class FeatureTypeSettings extends JalviewDialog * update min-max scaling if there is a range to work with, * else disable the widgets (this shouldn't happen if only * valid options are offered in the combo box) + * offset slider to have only non-negative values if necessary (JAL-2983) */ - scaleFactor = (max == min) ? 1f : 100f / (max - min); - float range = (max - min) * scaleFactor; - slider.setMinimum((int) (min * scaleFactor)); - slider.setMaximum((int) (max * scaleFactor)); - slider.setMajorTickSpacing((int) (range / 10f)); + slider.setSliderModel(min, max, min); + slider.setMajorTickSpacing( + (int) ((slider.getMaximum() - slider.getMinimum()) / 10f)); threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black); @@ -364,8 +361,8 @@ public class FeatureTypeSettings extends JalviewDialog fc.isAboveThreshold() ? ABOVE_THRESHOLD_OPTION : BELOW_THRESHOLD_OPTION); slider.setEnabled(true); - slider.setValue((int) (fc.getThreshold() * scaleFactor)); - thresholdValue.setText(String.valueOf(fc.getThreshold())); + slider.setSliderValue(fc.getThreshold()); + setThresholdValueText(fc.getThreshold()); thresholdValue.setEnabled(true); thresholdIsMin.setEnabled(true); } @@ -643,6 +640,7 @@ public class FeatureTypeSettings extends JalviewDialog thresholdValue_actionPerformed(); } }); + slider = new Slider(0f, 100f, 50f); slider.setPaintLabels(false); slider.setPaintTicks(true); slider.setBackground(Color.white); @@ -659,8 +657,7 @@ public class FeatureTypeSettings extends JalviewDialog { if (!adjusting) { - thresholdValue - .setText(String.valueOf(slider.getValue() / scaleFactor)); + setThresholdValueText(slider.getSliderValue()); thresholdValue.setBackground(Color.white); // to reset red for invalid sliderValueChanged(); } @@ -1050,8 +1047,8 @@ public class FeatureTypeSettings extends JalviewDialog 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)); + setThresholdValueText(f); + slider.setSliderValue(f); threshline.value = f; thresholdValue.setBackground(Color.white); // ok adjusting = false; @@ -1064,13 +1061,25 @@ public class FeatureTypeSettings extends JalviewDialog } /** + * Sets the text field for threshold value, rounded to four significant figures + * + * @param f + */ + void setThresholdValueText(float f) + { + BigDecimal formatted = new BigDecimal(f).round(FOUR_SIG_FIG) + .stripTrailingZeros(); + thresholdValue.setText(formatted.toPlainString()); + } + + /** * Action on change of threshold slider value. This may be done interactively * (by moving the slider), or programmatically (to update the slider after * manual input of a threshold value). */ protected void sliderValueChanged() { - threshline.value = getRoundedSliderValue(); + threshline.value = slider.getSliderValue(); /* * repaint alignment, but not Overview or structure, @@ -1079,21 +1088,6 @@ public class FeatureTypeSettings extends JalviewDialog colourChanged(false); } - /** - * 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 - * - * @return - */ - private float getRoundedSliderValue() - { - int value = slider.getValue(); - float f = value == slider.getMaximum() ? max - : (value == slider.getMinimum() ? min : value / scaleFactor); - return f; - } - void addActionListener(ActionListener listener) { if (featureSettings != null) diff --git a/src/jalview/gui/OptsAndParamsPage.java b/src/jalview/gui/OptsAndParamsPage.java index 5342c90..0f4d0e7 100644 --- a/src/jalview/gui/OptsAndParamsPage.java +++ b/src/jalview/gui/OptsAndParamsPage.java @@ -53,7 +53,6 @@ import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; -import javax.swing.JSlider; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.TitledBorder; @@ -277,7 +276,7 @@ public class OptsAndParamsPage boolean choice = false; - JComboBox choicebox; + JComboBox choicebox; JPanel controlPanel = new JPanel(); @@ -289,7 +288,7 @@ public class OptsAndParamsPage boolean integ = false; - Object lastVal; + String lastVal; ParameterI parameter; @@ -299,7 +298,7 @@ public class OptsAndParamsPage JButton showDesc = new JButton(); - JSlider slider = null; + Slider slider = null; JTextArea string = new JTextArea(); @@ -363,7 +362,7 @@ public class OptsAndParamsPage validate(); } - private void makeExpanderParam(ParameterI parm) + private void makeExpanderParam(final ParameterI parm) { setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT)); setBorder(new TitledBorder(parm.getName())); @@ -451,6 +450,9 @@ public class OptsAndParamsPage validate(); } + /** + * Action on input in text field + */ @Override public void actionPerformed(ActionEvent e) { @@ -467,24 +469,20 @@ public class OptsAndParamsPage private void checkIfModified() { - Object cstate = updateSliderFromValueField(); - boolean notmod = false; - if (cstate.getClass() == lastVal.getClass()) - { - if (cstate instanceof int[]) - { - notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]); - } - else if (cstate instanceof float[]) - { - notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]); - } - else if (cstate instanceof String[]) - { - notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0])); - } - } - pmdialogbox.argSetModified(this, !notmod); + Object cstate = getCurrentValue(); + boolean modified = !cstate.equals(lastVal); + pmdialogbox.argSetModified(this, modified); + } + + /** + * Answers the current value of the parameter, as text + * + * @return + */ + private String getCurrentValue() + { + return choice ? (String) choicebox.getSelectedItem() + : valueField.getText(); } @Override @@ -566,16 +564,20 @@ public class OptsAndParamsPage } + /** + * Action on change of slider value + */ @Override public void stateChanged(ChangeEvent e) { if (!adjusting) { - valueField.setText("" + ((integ) ? ("" + slider.getValue()) - : ("" + slider.getValue() / 1000f))); + float value = slider.getSliderValue(); + valueField.setText( + integ ? Integer.toString((int) value) + : Float.toString(value)); checkIfModified(); } - } public void updateControls(ParameterI parm) @@ -592,8 +594,6 @@ public class OptsAndParamsPage } else { - slider = new JSlider(); - slider.addChangeListener(this); valueField = new JTextField(); valueField.addActionListener(this); valueField.addKeyListener(new KeyListener() @@ -622,9 +622,11 @@ public class OptsAndParamsPage } }); valueField.setPreferredSize(new Dimension(60, 25)); + slider = makeSlider(parm.getValidValue()); + slider.addChangeListener(this); + controlPanel.add(slider, BorderLayout.WEST); controlPanel.add(valueField, BorderLayout.EAST); - } } @@ -634,8 +636,8 @@ public class OptsAndParamsPage { if (init) { - List vals = parm.getPossibleValues(); - for (Object val : vals) + List vals = parm.getPossibleValues(); + for (String val : vals) { choicebox.addItem(val); } @@ -651,96 +653,105 @@ public class OptsAndParamsPage valueField.setText(parm.getValue()); } } - lastVal = updateSliderFromValueField(); + lastVal = getCurrentValue(); adjusting = false; } - public Object updateSliderFromValueField() + private Slider makeSlider(ValueConstrainI validValue) + { + if (validValue != null) + { + final Number minValue = validValue.getMin(); + final Number maxValue = validValue.getMax(); + if (minValue != null && maxValue != null) + { + return new Slider(minValue.floatValue(), maxValue.floatValue(), + minValue.floatValue()); + } + } + + /* + * otherwise, a nominal slider which will not be visible + */ + return new Slider(0, 100, 50); + } + + public void updateSliderFromValueField() { - int iVal; - float fVal; if (validator != null) { + final Number minValue = validator.getMin(); + final Number maxValue = validator.getMax(); if (integ) { - iVal = 0; + int iVal = 0; try { valueField.setText(valueField.getText().trim()); iVal = Integer.valueOf(valueField.getText()); - if (validator.getMin() != null - && validator.getMin().intValue() > iVal) + if (minValue != null + && minValue.intValue() > iVal) { - iVal = validator.getMin().intValue(); + iVal = minValue.intValue(); // TODO: provide visual indication that hard limit was reached for // this parameter } - if (validator.getMax() != null - && validator.getMax().intValue() < iVal) + if (maxValue != null && maxValue.intValue() < iVal) { - iVal = validator.getMax().intValue(); - // TODO: provide visual indication that hard limit was reached for - // this parameter + iVal = maxValue.intValue(); } - } catch (Exception e) + } catch (NumberFormatException e) { + System.err.println(e.toString()); } - ; - // update value field to reflect any bound checking we performed. - valueField.setText("" + iVal); - if (validator.getMin() != null && validator.getMax() != null) + if (minValue != null || maxValue != null) { - slider.getModel().setRangeProperties(iVal, 1, - validator.getMin().intValue(), - validator.getMax().intValue() + 1, true); + valueField.setText(String.valueOf(iVal)); + slider.setSliderValue(iVal); } else { slider.setVisible(false); } - return new int[] { iVal }; } else { - fVal = 0f; + float fVal = 0f; try { valueField.setText(valueField.getText().trim()); fVal = Float.valueOf(valueField.getText()); - if (validator.getMin() != null - && validator.getMin().floatValue() > fVal) + if (minValue != null + && minValue.floatValue() > fVal) { - fVal = validator.getMin().floatValue(); + fVal = minValue.floatValue(); // TODO: provide visual indication that hard limit was reached for // this parameter // update value field to reflect any bound checking we performed. valueField.setText("" + fVal); } - if (validator.getMax() != null - && validator.getMax().floatValue() < fVal) + if (maxValue != null + && maxValue.floatValue() < fVal) { - fVal = validator.getMax().floatValue(); + fVal = maxValue.floatValue(); // TODO: provide visual indication that hard limit was reached for // this parameter // update value field to reflect any bound checking we performed. valueField.setText("" + fVal); } - } catch (Exception e) + } catch (NumberFormatException e) { + System.err.println(e.toString()); } - ; - if (validator.getMin() != null && validator.getMax() != null) + if (minValue != null && maxValue != null) { - slider.getModel().setRangeProperties((int) (fVal * 1000f), 1, - (int) (validator.getMin().floatValue() * 1000f), - 1 + (int) (validator.getMax().floatValue() * 1000f), - true); + slider.setSliderModel(minValue.floatValue(), + maxValue.floatValue(), fVal); } else { slider.setVisible(false); } - return new float[] { fVal }; } } else @@ -748,14 +759,8 @@ public class OptsAndParamsPage if (!choice) { slider.setVisible(false); - return new String[] { valueField.getText().trim() }; - } - else - { - return new String[] { (String) choicebox.getSelectedItem() }; } } - } } @@ -801,9 +806,9 @@ public class OptsAndParamsPage URL linkImageURL = getClass().getResource("/images/link.gif"); - Map optSet = new java.util.LinkedHashMap(); + Map optSet = new java.util.LinkedHashMap<>(); - Map paramSet = new java.util.LinkedHashMap(); + Map paramSet = new java.util.LinkedHashMap<>(); public Map getOptSet() { @@ -904,7 +909,7 @@ public class OptsAndParamsPage */ public List getCurrentSettings() { - List argSet = new ArrayList(); + List argSet = new ArrayList<>(); for (OptionBox opts : getOptSet().values()) { OptionI opt = opts.getOptionIfEnabled(); diff --git a/src/jalview/gui/Slider.java b/src/jalview/gui/Slider.java new file mode 100644 index 0000000..7f18461 --- /dev/null +++ b/src/jalview/gui/Slider.java @@ -0,0 +1,113 @@ +package jalview.gui; + +import javax.swing.JSlider; + +/** + * A modified {@code javax.swing.JSlider} that + *
    + *
  • supports float valued numbers (by scaling up integer values)
  • + *
  • rescales 'true' value range to avoid negative values, as these are not + * rendered correctly by some look and feel libraries
  • + *
+ * + * @author gmcarstairs + */ +@SuppressWarnings("serial") +public class Slider extends JSlider +{ + /* + * 'true' value corresponding to zero on the slider + */ + private float trueMin; + + /* + * 'true' value corresponding to slider maximum + */ + private float trueMax; + + /* + * scaleFactor applied to true value range to give a + * slider range of 0 - 100 + */ + private float sliderScaleFactor; + + /** + * Constructor that rescales min - max to 0 - 100 for the slider + * + * @param min + * @param max + * @param value + */ + public Slider(float min, float max, float value) + { + super(); + setSliderModel(min, max, value); + } + + /** + * Sets the min-max range and current value of the slider, with rescaling from + * true values to slider range as required + * + * @param min + * @param max + * @param value + */ + public void setSliderModel(float min, float max, float value) + { + trueMin = min; + trueMax = max; + setMinimum(0); + sliderScaleFactor = 100f / (max - min); + int sliderMax = (int) ((max - min) * sliderScaleFactor); + setMaximum(sliderMax); + setSliderValue(value); + } + + /** + * Answers the value of the slider position (descaled to 'true' value) + * + * @return + */ + public float getSliderValue() + { + /* + * convert slider max to 'true max' in case of rounding errors + */ + int value = getValue(); + return value == getMaximum() ? trueMax + : value / sliderScaleFactor + trueMin; + } + + /** + * Sets the slider value (scaled from the true value to the slider range) + * + * @param value + */ + public void setSliderValue(float value) + { + setValue(Math.round((value - trueMin) * sliderScaleFactor)); + } + + /** + * Answers the value of the slider position as a percentage between minimum and + * maximum of its range + * + * @return + */ + public float getSliderPercentageValue() + { + return (getValue() - getMinimum()) * 100f + / (getMaximum() - getMinimum()); + } + + /** + * Sets the slider position for a given percentage value of its min-max range + * + * @param pct + */ + public void setSliderPercentageValue(float pct) + { + float pc = pct / 100f * getMaximum(); + setValue((int) pc); + } +}