pipeline.parameter_cell_views.IntRangeSlider.java Source code

Java tutorial

Introduction

Here is the source code for pipeline.parameter_cell_views.IntRangeSlider.java

Source

/*******************************************************************************
 * Parismi v0.1
 * Copyright (c) 2009-2015 Cinquin Lab.
 * All rights reserved. This code is made available under a dual license:
 * the two-clause BSD license or the GNU Public License v2.
 ******************************************************************************/
package pipeline.parameter_cell_views;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.text.NumberFormat;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.commons.lang3.text.WordUtils;
import org.eclipse.jdt.annotation.NonNull;

import pipeline.misc_util.Utils;
import pipeline.misc_util.Utils.LogLevel;
import pipeline.parameters.AbstractParameter;
import pipeline.parameters.IntRangeParameter;
import pipeline.parameters.ParameterListener;

public class IntRangeSlider extends AbstractParameterCellView implements ParameterListener {

    private static final long serialVersionUID = 1L;

    private RangeSlider slider;
    private JTextField textMinimum;
    private JTextField textMaximum;
    private JTextField currentTextValue0, currentTextValue1;
    private JLabel parameterName;
    private JButton resetMin, resetMax, resetRange;
    private JTable table;
    private int tableRow;

    private int maximum;
    private int minimum;
    private int currentValue0, currentValue1;
    private JPanel textValueFrame;

    private IntRangeParameter currentParameter;

    private boolean silenceUpdate;

    private NumberFormat nf = NumberFormat.getInstance();

    @Override
    protected NumberFormat getNumberFormatter() {
        return nf;
    }

    public IntRangeSlider() {
        super();
        addMouseWheelListener(e -> {
            int rotation = e.getWheelRotation();
            int change = (int) ((currentValue1 - currentValue0 + 1) * rotation * Utils.getMouseWheelClickFactor());

            int newCurrentValue0 = currentValue0;
            int newCurrentValue1 = currentValue1;
            int saveIntMinimum = minimum;
            int saveIntMaximum = maximum;

            newCurrentValue0 += change;
            newCurrentValue1 += change;

            if (!((e.getModifiers() & java.awt.event.InputEvent.ALT_MASK) > 0)) {
                if (newCurrentValue1 > saveIntMaximum) {
                    int difference = newCurrentValue1 - newCurrentValue0;
                    newCurrentValue1 = saveIntMaximum;
                    newCurrentValue0 = newCurrentValue1 - difference;
                    if (newCurrentValue0 < 0)
                        Utils.log("<0", LogLevel.WARNING);
                }
                if (newCurrentValue0 < saveIntMinimum) {
                    int difference = newCurrentValue1 - newCurrentValue0;
                    newCurrentValue0 = saveIntMinimum;
                    newCurrentValue1 = newCurrentValue0 + difference;
                    if (newCurrentValue0 < 0)
                        Utils.log("<0", LogLevel.WARNING);
                }
            } else {
            }

            currentParameter
                    .setValue(new int[] { newCurrentValue0, newCurrentValue1, saveIntMinimum, saveIntMaximum });

            updateValues();
            currentParameter.fireValueChanged(false, false, true);
        });
        nf.setGroupingUsed(true);
        nf.setMaximumFractionDigits(3);
        nf.setMaximumIntegerDigits(12);

        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;

        parameterName = new JLabel("");

        c.gridx = 0;
        c.gridy = 0;
        c.weighty = 1.0;
        c.weightx = 0.0;
        c.gridwidth = 4;
        add(Box.createRigidArea(new Dimension(0, 5)), c);

        slider = new RangeSlider(0, 20);
        slider.addChangeListener(new sliderListener());
        c.gridx = 0;
        c.gridy = 1;
        c.weighty = 1.0;
        c.weightx = 0.0;
        c.gridwidth = 4;
        add(slider, c);
        c.gridwidth = 1;

        c.gridx = 0;
        c.gridy = 2;
        c.weighty = 1.0;
        c.weightx = 1.0;
        c.gridwidth = 4;
        Component comp = Box.createRigidArea(new Dimension(0, 10));
        ((JComponent) comp).setOpaque(true);
        add(comp, c);
        c.gridwidth = 1;

        currentTextValue0 = new JTextField("" + slider.getValue());
        currentTextValue1 = new JTextField("" + slider.getUpperValue());
        currentTextValue0.addActionListener(new textBoxListenerTriggersUpdate());
        currentTextValue1.addActionListener(new textBoxListenerTriggersUpdate());
        Font smallerFont = new Font(currentTextValue0.getFont().getName(), currentTextValue0.getFont().getStyle(),
                currentTextValue0.getFont().getSize() - 2);
        textMinimum = new JTextField("0");
        textMinimum.setFont(smallerFont);
        textMinimum.addActionListener(new minimumListener());
        textMaximum = new JTextField("50");
        textMaximum.setFont(smallerFont);
        textMaximum.addActionListener(new maximumListener());
        textMaximum.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                if (!silenceUpdate) {
                    slider.setMinimum(parseTextBox(textMinimum).intValue());
                    minimum = slider.getMinimum();
                    slider.setMaximum(parseTextBox(textMaximum).intValue());
                    maximum = slider.getMaximum();
                    slider.setValue(parseTextBox(currentTextValue0).intValue());
                    slider.setUpperValue(parseTextBox(currentTextValue1).intValue());
                    currentValue0 = slider.getValue();
                    currentValue1 = slider.getUpperValue();

                    currentParameter.setValue(new int[] { currentValue0, currentValue1, minimum, maximum });
                }
            }

        });

        textValueFrame = new JPanel();
        textValueFrame.setBackground(getBackground());
        textValueFrame.setLayout(new GridBagLayout());

        c.gridx = 0;
        c.gridy = 0;
        c.weighty = 1.0;
        c.weightx = 0.1;
        textValueFrame.add(textMinimum, c);

        c.gridx = 1;
        c.gridy = 0;
        c.weighty = 1.0;
        c.weightx = 0.3;
        textValueFrame.add(currentTextValue0, c);

        c.gridx = 2;
        c.gridy = 0;
        c.weighty = 1.0;
        c.weightx = 0.3;
        textValueFrame.add(currentTextValue1, c);

        c.gridx = 3;
        c.gridy = 0;
        c.weighty = 1.0;
        c.weightx = 0.1;
        textValueFrame.add(textMaximum, c);

        c.gridx = 0;
        c.gridy = 3;
        c.weighty = 1.0;
        c.weightx = 0.3;
        c.gridwidth = 4;
        add(textValueFrame, c);
        c.gridwidth = 1;

        parameterName = new JLabel("parameter");
        c.gridx = 0;
        c.gridy = 4;
        c.weighty = 1.0;
        c.weightx = 0.01;
        c.gridwidth = 1;
        add(parameterName, c);

        resetMin = new JButton("Min");
        resetMin.setActionCommand("Reset Min");
        resetMin.addActionListener(new buttonListener());
        resetMax = new JButton("Max");
        resetMax.setActionCommand("Reset Max");
        resetMax.addActionListener(new buttonListener());
        resetRange = new JButton("MinMax");
        resetRange.setActionCommand("Reset Range");
        resetRange.addActionListener(new buttonListener());

        c.gridx = 1;
        c.gridy = 4;
        c.weighty = 1.0;
        c.weightx = 0.2;
        c.gridwidth = 1;
        add(resetMin, c);

        c.gridx = 2;
        c.gridy = 4;
        c.weighty = 1.0;
        c.weightx = 0.2;
        c.gridwidth = 1;
        add(resetMax, c);

        c.gridx = 3;
        c.gridy = 4;
        c.weighty = 1.0;
        c.weightx = 0.2;
        c.gridwidth = 1;
        add(resetRange, c);

    }

    private class buttonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            currentParameter.buttonPressed(e.getActionCommand(), false, null);
            // now update text boxes and slider in "silenced" mode
            int[] intValues = (int[]) (currentParameter.getValue());
            silenceUpdate = true;
            slider.setValue(intValues[0]);
            slider.setUpperValue(intValues[1]);
            updateTextValue(currentTextValue0, intValues[0]);
            updateTextValue(currentTextValue1, intValues[1]);
            updateTextValue(textMinimum, intValues[2]);
            updateTextValue(textMaximum, intValues[3]);
            minimum = intValues[2];
            maximum = intValues[3];
            slider.setMaximum(maximum);
            slider.setMinimum(minimum);
            parameterName.setText(currentParameter.getParamNameDescription()[0]);
            parameterName.setVisible(!currentParameter.getParamNameDescription()[0].equals(""));
            textMinimum.setEditable(currentParameter.editable()[0]);
            textMaximum.setEditable(currentParameter.editable()[1]);
            setToolTipText(
                    Utils.encodeHTML(WordUtils.wrap(currentParameter.getParamNameDescription()[1], 50, null, true))
                            .replace("\n", "<br>\n"));
            int height_wanted = (int) getPreferredSize().getHeight();
            if (height_wanted > table.getRowHeight(tableRow))
                table.setRowHeight(tableRow, height_wanted);

            silenceUpdate = false;
        }
    }

    private class minimumListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!silenceUpdate) {
                minimum = parseTextBox(textMinimum).intValue();
                currentParameter.updateBounds(minimum, maximum);
                updateValues();
            }
        }
    }

    private class maximumListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!silenceUpdate) {
                maximum = parseTextBox(textMaximum).intValue();
                currentParameter.updateBounds(minimum, maximum);
                updateValues();
            }
        }
    }

    private class textBoxListenerTriggersUpdate implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!silenceUpdate) {
                JTextField source = (JTextField) e.getSource();
                try {
                    minimum = slider.getMinimum();
                    maximum = slider.getMaximum();
                    currentValue0 = parseTextBox(currentTextValue0).intValue();
                    currentValue1 = parseTextBox(currentTextValue1).intValue();
                } catch (NumberFormatException nfe) {
                    Utils.log("cant parse " + source.getText() + " as an int; ignoring", LogLevel.ERROR);
                    return;
                }
                currentParameter.setValue(new int[] { currentValue0, currentValue1, minimum, maximum });
                updateParameterValuesButNotMainTextBox(); // In case parameter adjusted minimum or maximum
                currentParameter.fireValueChanged(false, false, true);
            }
        }
    }

    private transient boolean wasChanging = false;

    private class sliderListener implements ChangeListener {
        @Override
        public void stateChanged(ChangeEvent e) {
            if (!silenceUpdate) {
                if (!slider.getValueIsAdjusting()) {
                    if ((currentValue0 == slider.getValue()) && (currentValue1 == slider.getUpperValue())) {
                        if (wasChanging) {
                            currentParameter.fireValueChanged(false, false, true);
                            wasChanging = false;
                        }
                        return;
                    }
                    currentValue0 = slider.getValue();
                    currentValue1 = slider.getUpperValue();
                    currentParameter.setValue(new int[] { currentValue0, currentValue1, minimum, maximum });
                    updateParameterValuesButNotMainTextBox(); // In case parameter adjusted minimum or maximum
                    currentParameter.fireValueChanged(false, false, true);
                } else { // value is still adjusting
                    wasChanging = true;
                    if ((currentValue0 == slider.getValue()) && (currentValue1 == slider.getUpperValue()))
                        return;
                    currentValue0 = slider.getValue();
                    currentValue1 = slider.getUpperValue();
                    currentTextValue0.setText("" + nf.format(currentValue0));
                    currentTextValue1.setText("" + nf.format(currentValue1));
                    currentParameter.setValue(new int[] { currentValue0, currentValue1, minimum, maximum });
                    updateParameterValuesButNotMainTextBox(); // In case parameter adjusted minimum or maximum
                    currentParameter.fireValueChanged(true, false, true);
                }
            }
        }
    }

    private void updateTextValue(JTextField f, int v) {
        f.setText("" + nf.format(v));
    }

    private boolean evenTableRow;

    private void updateValues() {
        boolean saveSilenceUpdate = silenceUpdate;

        try {
            int[] intValues = (int[]) (currentParameter.getValue());
            silenceUpdate = true;

            updateTextValue(currentTextValue0, intValues[0]);
            updateTextValue(currentTextValue1, intValues[1]);
            updateTextValue(textMinimum, intValues[2]);
            updateTextValue(textMaximum, intValues[3]);
            minimum = intValues[2];
            maximum = intValues[3];
            currentValue0 = intValues[0];
            currentValue1 = intValues[1];

            slider.setMaximum(maximum);
            slider.setMinimum(minimum);
            slider.setValue(intValues[0]);
            slider.setUpperValue(intValues[1]);
            revalidate();
        } finally {
            silenceUpdate = saveSilenceUpdate;
        }
    }

    /**
     * Read parameter value, min, and max and update our display.
     */
    private void updateParameterValuesButNotMainTextBox() {
        int[] intValues = (int[]) (currentParameter.getValue());
        currentValue0 = intValues[0];
        currentValue1 = intValues[1];
        minimum = intValues[2];
        maximum = intValues[3];

        boolean saveSilenceUpdate = silenceUpdate;
        silenceUpdate = true;
        updateTextValue(textMinimum, minimum);
        updateTextValue(textMaximum, maximum);

        slider.setMaximum(maximum);
        slider.setMinimum(minimum);
        slider.setValue(currentValue0);
        slider.setUpperValue(currentValue1);
        slider.repaint();

        silenceUpdate = saveSilenceUpdate;
    }

    @Override
    protected Component getRendererOrEditorComponent(JTable table0, @NonNull Object value, boolean isSelected,
            boolean hasFocus, int row, int column, boolean rendererCalled) {

        if (currentParameter != null) {
            currentParameter.removeListener(this);
        }

        currentParameter = (IntRangeParameter) value;
        currentParameter.addGUIListener(this);

        table = table0;
        tableRow = row;

        evenTableRow = (row % 2 == 0);
        setOpaque(true);
        if (evenTableRow) {
            this.setBackground(Utils.COLOR_FOR_EVEN_ROWS);
        } else
            this.setBackground(Utils.COLOR_FOR_ODD_ROWS);
        textValueFrame.setBackground(getBackground());

        updateValues();

        parameterName.setText(currentParameter.getParamNameDescription()[0]);
        parameterName.setVisible(!currentParameter.getParamNameDescription()[0].equals(""));
        textMinimum.setEditable(currentParameter.editable()[0]);
        textMaximum.setEditable(currentParameter.editable()[1]);
        this.setToolTipText(currentParameter.getParamNameDescription()[1]);
        int height_wanted = (int) getPreferredSize().getHeight();
        if (height_wanted > table0.getRowHeight(row))
            table0.setRowHeight(row, height_wanted);
        if (!rendererCalled) {
            slider.setBounds(table0.getCellRect(row, column, false));
            slider.updateUI();
        }

        silenceUpdate = false;
        return this;
    }

    @Override
    public Object getCellEditorValue() {
        return currentParameter;
    }

    private void updateDisplay() {
        boolean saveSilenceUpdate = silenceUpdate;
        silenceUpdate = true;

        updateValues();

        this.revalidate();
        silenceUpdate = saveSilenceUpdate;
    }

    @Override
    public void parameterValueChanged(boolean stillChanging, AbstractParameter parameterWhoseValueChanged,
            boolean keepQuiet) {
        if (!silenceUpdate) {
            updateDisplay();
        }
    }

    @Override
    public void parameterPropertiesChanged(AbstractParameter parameterWhosePropertiesChanged) {
        if (!silenceUpdate) {
            updateDisplay();
        }
    }

    @Override
    public void buttonPressed(String commandName, AbstractParameter parameter, ActionEvent event) {
    }

    @Override
    public boolean alwaysNotify() {
        return false;
    }

}