package gdsc.foci.gui; /*----------------------------------------------------------------------------- * GDSC Plugins for ImageJ * * Copyright (C) 2011 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.border.EmptyBorder; /** * Dialog that can be used to reconfigure the minimum and maximum limits for a JSlider */ public class SliderLimitHelper extends JDialog implements ActionListener { private static final long serialVersionUID = 2830394230842354064L; private final JPanel contentPanel = new JPanel(); private JLabel lblParametername; private JFormattedTextField txtMinimum; private JFormattedTextField txtMaximum; private boolean oked = false; private double lowerBound = Double.NEGATIVE_INFINITY; private double upperBound = Double.POSITIVE_INFINITY; /** * Launch the application. */ public static void main(String[] args) { try { SliderLimitHelper dialog = new SliderLimitHelper(); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } public SliderLimitHelper(Component parent) { init(); setLocationRelativeTo(parent); } /** * Create the dialog. */ public SliderLimitHelper() { addWindowListener(new WindowAdapter() { @Override public void windowActivated(WindowEvent e) { validMin(); validMax(); } }); init(); } private void init() { setModalityType(ModalityType.DOCUMENT_MODAL); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setBounds(100, 100, 197, 145); getContentPane().setLayout(new BorderLayout()); contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); getContentPane().add(contentPanel, BorderLayout.CENTER); GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[] { 0, 0, 0 }; gridBagLayout.rowHeights = new int[] { 0, 0, 0, 0 }; gridBagLayout.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE }; gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, Double.MIN_VALUE }; contentPanel.setLayout(gridBagLayout); { lblParametername = new JLabel("ParameterName"); GridBagConstraints gbc_lblParametername = new GridBagConstraints(); gbc_lblParametername.anchor = GridBagConstraints.WEST; gbc_lblParametername.gridwidth = 2; gbc_lblParametername.insets = new Insets(0, 0, 5, 5); gbc_lblParametername.gridx = 0; gbc_lblParametername.gridy = 0; contentPanel.add(lblParametername, gbc_lblParametername); } { JLabel lblMinimum = new JLabel("Minimum"); GridBagConstraints gbc_lblMinimum = new GridBagConstraints(); gbc_lblMinimum.anchor = GridBagConstraints.EAST; gbc_lblMinimum.insets = new Insets(0, 0, 5, 5); gbc_lblMinimum.gridx = 0; gbc_lblMinimum.gridy = 1; contentPanel.add(lblMinimum, gbc_lblMinimum); } { txtMinimum = new JFormattedTextField(); txtMinimum.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("textFormatter")) { validMin(); } } }); txtMinimum.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { validMin(); } }); txtMinimum.setValue(new Double(0)); GridBagConstraints gbc_txtMinimum = new GridBagConstraints(); gbc_txtMinimum.insets = new Insets(0, 0, 5, 0); gbc_txtMinimum.fill = GridBagConstraints.HORIZONTAL; gbc_txtMinimum.gridx = 1; gbc_txtMinimum.gridy = 1; contentPanel.add(txtMinimum, gbc_txtMinimum); } { JLabel lblMaximum = new JLabel("Maximum"); GridBagConstraints gbc_lblMaximum = new GridBagConstraints(); gbc_lblMaximum.anchor = GridBagConstraints.EAST; gbc_lblMaximum.insets = new Insets(0, 0, 0, 5); gbc_lblMaximum.gridx = 0; gbc_lblMaximum.gridy = 2; contentPanel.add(lblMaximum, gbc_lblMaximum); } { txtMaximum = new JFormattedTextField(); txtMaximum.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("textFormatter")) { validMax(); } } }); txtMaximum.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { validMax(); } }); txtMaximum.setValue(new Double(10)); GridBagConstraints gbc_txtMaximum = new GridBagConstraints(); gbc_txtMaximum.fill = GridBagConstraints.HORIZONTAL; gbc_txtMaximum.gridx = 1; gbc_txtMaximum.gridy = 2; contentPanel.add(txtMaximum, gbc_txtMaximum); } { JPanel buttonPane = new JPanel(); buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); getContentPane().add(buttonPane, BorderLayout.SOUTH); { JButton okButton = new JButton("OK"); okButton.addActionListener(this); okButton.setActionCommand("OK"); buttonPane.add(okButton); getRootPane().setDefaultButton(okButton); } { JButton cancelButton = new JButton("Cancel"); cancelButton.addActionListener(this); cancelButton.setActionCommand("Cancel"); buttonPane.add(cancelButton); } } } /** * @param name The parameter name */ public void setParameterName(String name) { this.lblParametername.setText(name); } /** * @param minimum * the minimum to set */ public void setMinimum(double minimum) { this.txtMinimum.setValue(minimum); } /** * @return the minimum */ public double getMinimum() { return (Double) txtMinimum.getValue(); } /** * @param maximum * the maximum to set */ public void setMaximum(double maximum) { this.txtMaximum.setValue(maximum); } /** * @return the maximum */ public double getMaximum() { return (Double) txtMaximum.getValue(); } /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == "OK") { System.out.println("Validate input"); if (valid()) { oked = true; dispose(); } } if (e.getActionCommand() == "Cancel") { dispose(); } } private boolean valid() { if (!validMin()) { return false; } if (!validMax()) { return false; } double min = getMinimum(); double max = getMaximum(); if (max <= min) { // Invert for convenience setMinimum(max); setMaximum(min); } return true; } private boolean validMin() { return valid(txtMinimum); } private boolean validMax() { return valid(txtMaximum); } private boolean valid(JFormattedTextField txtField) { if (isEmpty(txtField)) return true; try { double value = Double.parseDouble(txtField.getText()); if (value >= lowerBound && value <= upperBound) { txtField.setForeground(Color.BLACK); return true; } } catch (NumberFormatException e) { } txtField.setForeground(Color.RED); return false; } private boolean isEmpty(JFormattedTextField txtField) { if (txtField.getText() == null || txtField.getText().equals("")) { txtField.setForeground(Color.BLACK); return true; } return false; } /** * @return the true if the dialog was Oked */ public boolean getOked() { return oked; } /** * @param lowerBound * the lowerBound to set */ public void setLowerBound(double lowerBound) { this.lowerBound = lowerBound; String tooltip = null; if (lowerBound != Double.NEGATIVE_INFINITY) { tooltip = "Lower bound = " + lowerBound; } this.txtMinimum.setToolTipText(tooltip); } /** * @return the lowerBound */ public double getLowerBound() { return lowerBound; } /** * @param upperBound * the upperBound to set */ public void setUpperBound(double upperBound) { this.upperBound = upperBound; String tooltip = null; if (upperBound != Double.POSITIVE_INFINITY) { tooltip = "Upper bound = " + upperBound; } this.txtMaximum.setToolTipText(tooltip); } /** * @return the upperBound */ public double getUpperBound() { return upperBound; } /** * Updates the minimum/maximum for a JSlider. Presents a dialog where the user can * configure the limits using text input. The limits will be multiplied by the * scale factor before setting the slider limits (allowing fractional input * to be modelled with the integer scale on the slider). * * @param slider * @param title * The title of the dialog * @param scaleFactor * The scalefactor applied to the input text to set the slider limits * @return true if the limits were updated */ public static boolean updateRangeLimits(JSlider slider, String title, double scaleFactor) { return updateRangeLimits(slider, title, scaleFactor, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } /** * Updates the minimum/maximum for a JSlider. Presents a dialog where the user can * configure the limits using text input. The limits will be multiplied by the * scale factor before setting the slider limits (allowing fractional input * to be modelled with the integer scale on the slider). * * @param slider * @param title * The title of the dialog * @param scaleFactor * The scalefactor applied to the input text to set the slider limits * @param lowerBound * Lower bound for the range * @param upperBound * Upper bound for the range * @return true if the limits were updated */ public static boolean updateRangeLimits(JSlider slider, String title, double scaleFactor, double lowerBound, double upperBound) { SliderLimitHelper dialog = new SliderLimitHelper(slider); dialog.setTitle(title); dialog.setParameterName(title); dialog.setMinimum(slider.getMinimum() / scaleFactor); dialog.setMaximum(slider.getMaximum() / scaleFactor); dialog.setLowerBound(lowerBound); dialog.setUpperBound(upperBound); dialog.setVisible(true); if (dialog.getOked()) { slider.setMinimum((int) (dialog.getMinimum() * scaleFactor)); slider.setMaximum((int) (dialog.getMaximum() * scaleFactor)); return true; } return false; } }