/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> Website : http://www.gephi.org This file is part of Gephi. Gephi is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gephi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Gephi. If not, see <http://www.gnu.org/licenses/>. */ package org.gephi.ui.components; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * * @author Mathieu Bastian */ public class JRangeSliderPanel extends javax.swing.JPanel { public static final String LOWER_BOUND = "lowerbound"; public static final String UPPER_BOUND = "upperbound"; private static final int SLIDER_MAXIMUM = 1000; private String lowerBound = "NaN"; private String upperBound = "NaN"; private Range range; /** Creates new form JRangeSliderPanel */ public JRangeSliderPanel() { initComponents(); ((JRangeSlider)rangeSlider).setUpperValue(1000); rangeSlider.setOpaque(false); lowerBoundTextField.setOpaque(false); upperBoundTextField.setOpaque(false); lowerBoundTextField.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { lowerBoundTextField.setEnabled(true); lowerBoundTextField.selectAll(); } }); lowerBoundTextField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!lowerBoundTextField.getText().equals(lowerBound)) { lowerBound = lowerBoundTextField.getText(); if (range != null) { range.setLowerBound(lowerBound); firePropertyChange(LOWER_BOUND, null, lowerBound); } } else { lowerBound = lowerBoundTextField.getText(); } refreshBoundTexts(); lowerBoundTextField.setEnabled(false); } }); lowerBoundTextField.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { lowerBoundTextField.setEnabled(false); } }); upperBoundTextField.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { upperBoundTextField.setEnabled(true); upperBoundTextField.selectAll(); } }); upperBoundTextField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!upperBoundTextField.getText().equals(upperBound)) { upperBound = upperBoundTextField.getText(); if (range != null) { range.setUpperBound(upperBound); firePropertyChange(UPPER_BOUND, null, upperBound); } } else { upperBound = upperBoundTextField.getText(); } refreshBoundTexts(); upperBoundTextField.setEnabled(false); } }); upperBoundTextField.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { upperBoundTextField.setEnabled(false); } }); rangeSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JRangeSlider source = (JRangeSlider) e.getSource(); if (!source.getValueIsAdjusting()) { if (range != null) { range.refreshBounds(); refreshBoundTexts(); } } } }); } private void refreshBoundTexts() { if (range != null) { lowerBound = range.lowerBound.toString(); upperBound = range.upperBound.toString(); lowerBoundTextField.setText(lowerBound); upperBoundTextField.setText(upperBound); } } public JRangeSlider getSlider() { return (JRangeSlider) rangeSlider; } public Range getRange() { return range; } public void setRange(Range range) { if (!range.min.equals(range.max)) { this.range = range; range.refreshSlider(); refreshBoundTexts(); } else { lowerBound = "NaN"; upperBound = "NaN"; lowerBoundTextField.setText(lowerBound); upperBoundTextField.setText(upperBound); } } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; rangeSlider = new JRangeSlider(); lowerBoundTextField = new javax.swing.JTextField(); upperBoundTextField = new javax.swing.JTextField(); setOpaque(false); setLayout(new java.awt.GridBagLayout()); rangeSlider.setMaximum(1000); rangeSlider.setValue(0); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; add(rangeSlider, gridBagConstraints); lowerBoundTextField.setText(org.openide.util.NbBundle.getMessage(JRangeSliderPanel.class, "JRangeSliderPanel.lowerBoundTextField.text")); // NOI18N lowerBoundTextField.setBorder(null); lowerBoundTextField.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); add(lowerBoundTextField, gridBagConstraints); upperBoundTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT); upperBoundTextField.setText(org.openide.util.NbBundle.getMessage(JRangeSliderPanel.class, "JRangeSliderPanel.upperBoundTextField.text")); // NOI18N upperBoundTextField.setBorder(null); upperBoundTextField.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5); add(upperBoundTextField, gridBagConstraints); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField lowerBoundTextField; private javax.swing.JSlider rangeSlider; private javax.swing.JTextField upperBoundTextField; // End of variables declaration//GEN-END:variables public static class Range { private JRangeSliderPanel slider; private Object min; private Object max; private Object lowerBound; private Object upperBound; private int sliderLowValue = -1; private int sliderUpValue = -1; public Range(JRangeSliderPanel slider, Object min, Object max) { this.slider = slider; this.min = min; this.max = max; this.lowerBound = min; this.upperBound = max; } public Range(JRangeSliderPanel slider, Object min, Object max, Object lowerBound, Object upperBound) { this.slider = slider; this.min = min; this.max = max; this.lowerBound = lowerBound; this.upperBound = upperBound; } public Object getLowerBound() { return lowerBound; } public Object getUpperBound() { return upperBound; } private void setLowerBound(String bound) { if (min instanceof Float) { try { Float l = Float.parseFloat(bound); if (l < (Float) min) { lowerBound = min; } else if (l > (Float) upperBound) { lowerBound = upperBound; } else { lowerBound = l; } } catch (Exception e) { } } else if (min instanceof Double) { try { Double l = Double.parseDouble(bound); if (l < (Double) min) { lowerBound = min; } else if (l > (Double) upperBound) { lowerBound = upperBound; } else { lowerBound = l; } } catch (Exception e) { } } else if (min instanceof Integer) { try { Integer l = Integer.parseInt(bound); if (l < (Integer) min) { lowerBound = min; } else if (l > (Integer) upperBound) { lowerBound = upperBound; } else { lowerBound = l; } } catch (Exception e) { } } else if (min instanceof Long) { try { Long l = Long.parseLong(bound); if (l < (Long) min) { lowerBound = min; } else if (l > (Long) upperBound) { lowerBound = upperBound; } else { lowerBound = l; } } catch (Exception e) { } } refreshSlider(); } private void setUpperBound(String bound) { if (min instanceof Float) { try { Float l = Float.parseFloat(bound); if (l > (Float) max) { upperBound = max; } else if (l < (Float) lowerBound) { upperBound = lowerBound; } else { upperBound = l; } } catch (Exception e) { } } else if (min instanceof Double) { try { Double l = Double.parseDouble(bound); if (l > (Double) max) { upperBound = max; } else if (l < (Double) lowerBound) { upperBound = lowerBound; } else { upperBound = l; } } catch (Exception e) { } } else if (min instanceof Integer) { try { Integer l = Integer.parseInt(bound); if (l > (Integer) max) { upperBound = max; } else if (l < (Integer) lowerBound) { upperBound = lowerBound; } else { upperBound = l; } } catch (Exception e) { } } else if (min instanceof Long) { try { Long l = Long.parseLong(bound); if (l > (Long) max) { upperBound = max; } else if (l < (Long) lowerBound) { upperBound = lowerBound; } else { upperBound = l; } } catch (Exception e) { } } refreshSlider(); } private void refreshSlider() { double normalizedLow = 0.; double normalizedUp = 1.; if (min instanceof Float) { normalizedLow = ((Float) lowerBound - (Float) min) / ((Float) max - (Float) min); normalizedUp = ((Float) upperBound - (Float) min) / ((Float) max - (Float) min); } else if (min instanceof Double) { normalizedLow = ((Double) lowerBound - (Double) min) / ((Double) max - (Double) min); normalizedUp = ((Double) upperBound - (Double) min) / ((Double) max - (Double) min); } else if (min instanceof Integer) { normalizedLow = ((Integer) lowerBound - (Integer) min) / (double) ((Integer) max - (Integer) min); normalizedUp = ((Integer) upperBound - (Integer) min) / (double) ((Integer) max - (Integer) min); } else if (min instanceof Long) { normalizedLow = ((Long) lowerBound - (Long) min) / (double) ((Long) max - (Long) min); normalizedUp = ((Long) upperBound - (Long) min) / (double) ((Long) max - (Long) min); } sliderLowValue = (int) (normalizedLow * SLIDER_MAXIMUM); sliderUpValue = (int) (normalizedUp * SLIDER_MAXIMUM); slider.getSlider().setValue(sliderLowValue); slider.getSlider().setUpperValue(sliderUpValue); } private void refreshBounds() { boolean lowerChanged = slider.getSlider().getValue() != sliderLowValue; boolean upperChanged = slider.getSlider().getUpperValue() != sliderUpValue; sliderLowValue = slider.getSlider().getValue(); sliderUpValue = slider.getSlider().getUpperValue(); double normalizedLow = slider.getSlider().getValue() / (double) SLIDER_MAXIMUM; double normalizedUp = slider.getSlider().getUpperValue() / (double) SLIDER_MAXIMUM; if (min instanceof Float) { lowerBound = lowerChanged ? new Float((normalizedLow * ((Float) max - (Float) min)) + (Float) min) : lowerBound; upperBound = upperChanged ? new Float((normalizedUp * ((Float) max - (Float) min)) + (Float) min) : upperBound; } else if (min instanceof Double) { lowerBound = lowerChanged ? new Double((normalizedLow * ((Double) max - (Double) min)) + (Double) min) : lowerBound; upperBound = upperChanged ? new Double((normalizedUp * ((Double) max - (Double) min)) + (Double) min) : upperBound; } else if (min instanceof Integer) { lowerBound = lowerChanged ? new Integer((int) ((normalizedLow * ((Integer) max - (Integer) min)) + (Integer) min)) : lowerBound; upperBound = upperChanged ? new Integer((int) ((normalizedUp * ((Integer) max - (Integer) min)) + (Integer) min)) : upperBound; } else if (min instanceof Long) { lowerBound = lowerChanged ? new Long((long) ((normalizedLow * ((Long) max - (Long) min)) + (Long) min)) : lowerBound; upperBound = upperChanged ? new Long((long) ((normalizedUp * ((Long) max - (Long) min)) + (Long) min)) : upperBound; } if (lowerChanged) { slider.firePropertyChange(LOWER_BOUND, null, lowerBound); } if (upperChanged) { slider.firePropertyChange(UPPER_BOUND, null, upperBound); } } } }