/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.ejs.control.swing; import javax.swing.JLabel; import javax.swing.JSlider; import javax.swing.SwingConstants; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import org.opensourcephysics.ejs.control.ControlElement; import org.opensourcephysics.ejs.control.value.DoubleValue; import org.opensourcephysics.ejs.control.value.Value; /** * A slider to display double values. When the value is changing it * invokes all VARIABLE_CHANGED actions. When the value is finally set, * it invokes all ACTION actions. */ public class ControlSlider extends ControlSwingElement { static private final int RESOLUTION = 100000; static private final int VARIABLE = 0; protected JSlider slider; private DoubleValue internalValue; private boolean recalculate = true, defaultValueSet; private int ticks = 0; private double defaultValue, scale, minimum = 0.0, maximum = 1.0; private TitledBorder titledBorder; private EtchedBorder etchedBorder; private java.text.DecimalFormat format = null, ticksFormat = null; // ------------------------------------------------ // Visual component // ------------------------------------------------ /** * Constructor ControlSlider * @param _visual */ public ControlSlider(Object _visual) { super(_visual); } protected java.awt.Component createVisual(Object _visual) { if(_visual instanceof JSlider) { slider = (JSlider) _visual; } else { slider = new JSlider(); slider.setPaintLabels(false); slider.setPaintTicks(false); slider.setPaintTrack(true); } slider.setMinimum(0); slider.setMaximum(RESOLUTION); slider.setValue(0); etchedBorder = new EtchedBorder(EtchedBorder.LOWERED); titledBorder = new TitledBorder(etchedBorder, ""); //$NON-NLS-1$ titledBorder.setTitleJustification(TitledBorder.CENTER); slider.setBorder(etchedBorder); defaultValue = 0.0; defaultValueSet = false; internalValue = new DoubleValue(defaultValue); minimum = 0.0; maximum = 1.0; scale = RESOLUTION*(maximum-minimum); setMaximum(maximum); internalValue.value = minimum+slider.getValue()/scale; slider.addChangeListener(new MyChangeListener()); slider.addMouseListener(new MyMouseListener()); return slider; } private void setTheValue(double val) { internalValue.value = val; recalculate = false; slider.setValue((int) ((internalValue.value-minimum)*scale)); recalculate = true; if(format!=null) { titledBorder.setTitle(format.format(internalValue.value)); slider.repaint(); } } public void reset() { if(defaultValueSet) { setTheValue(defaultValue); variableChanged(VARIABLE, internalValue); } } // ------------------------------------------------ // Properties // ------------------------------------------------ static private java.util.ArrayList<String> infoList = null; public java.util.ArrayList<String> getPropertyList() { if(infoList==null) { infoList = new java.util.ArrayList<String>(); infoList.add("variable"); //$NON-NLS-1$ infoList.add("value"); //$NON-NLS-1$ infoList.add("minimum"); //$NON-NLS-1$ infoList.add("maximum"); //$NON-NLS-1$ infoList.add("pressaction"); //$NON-NLS-1$ infoList.add("dragaction"); //$NON-NLS-1$ infoList.add("action"); //$NON-NLS-1$ infoList.add("format"); //$NON-NLS-1$ infoList.add("ticks"); //$NON-NLS-1$ infoList.add("ticksFormat"); //$NON-NLS-1$ infoList.add("closest"); //$NON-NLS-1$ infoList.add("orientation"); //$NON-NLS-1$ infoList.addAll(super.getPropertyList()); } return infoList; } public String getPropertyInfo(String _property) { if(_property.equals("variable")) { //$NON-NLS-1$ return "int|double"; //$NON-NLS-1$ } if(_property.equals("value")) { //$NON-NLS-1$ return "int|double"; //$NON-NLS-1$ } if(_property.equals("minimum")) { //$NON-NLS-1$ return "int|double"; //$NON-NLS-1$ } if(_property.equals("maximum")) { //$NON-NLS-1$ return "int|double"; //$NON-NLS-1$ } if(_property.equals("pressaction")) { //$NON-NLS-1$ return "Action CONSTANT"; //$NON-NLS-1$ } if(_property.equals("dragaction")) { //$NON-NLS-1$ return "Action CONSTANT"; //$NON-NLS-1$ } if(_property.equals("action")) { //$NON-NLS-1$ return "Action CONSTANT"; //$NON-NLS-1$ } if(_property.equals("format")) { //$NON-NLS-1$ return "Format|Object TRANSLATABLE"; //$NON-NLS-1$ } if(_property.equals("ticks")) { //$NON-NLS-1$ return "int BASIC"; //$NON-NLS-1$ } if(_property.equals("ticksFormat")) { //$NON-NLS-1$ return "Format|Object BASIC TRANSLATABLE"; //$NON-NLS-1$ } if(_property.equals("closest")) { //$NON-NLS-1$ return "boolean BASIC"; //$NON-NLS-1$ } if(_property.equals("orientation")) { //$NON-NLS-1$ return "Orientation|int BASIC"; //$NON-NLS-1$ } if(_property.equals("enabled")) { //$NON-NLS-1$ return "boolean"; // Not hidden //$NON-NLS-1$ } return super.getPropertyInfo(_property); } // ------------------------------------------------ // Set and Get the values of the properties // ------------------------------------------------ public void setValue(int _index, Value _value) { switch(_index) { case VARIABLE : if(internalValue.value!=_value.getDouble()) { setTheValue(_value.getDouble()); } break; case 1 : defaultValueSet = true; defaultValue = _value.getDouble(); setActive(false); reset(); setActive(true); break; case 2 : setMinimum(_value.getDouble()); break; case 3 : setMaximum(_value.getDouble()); break; case 4 : // pressaction removeAction(ControlSwingElement.ACTION_PRESS, getProperty("pressaction")); //$NON-NLS-1$ addAction(ControlSwingElement.ACTION_PRESS, _value.getString()); break; case 5 : // dragaction removeAction(ControlElement.VARIABLE_CHANGED, getProperty("dragaction")); //$NON-NLS-1$ addAction(ControlElement.VARIABLE_CHANGED, _value.getString()); break; case 6 : // pressaction removeAction(ControlElement.ACTION, getProperty("action")); //$NON-NLS-1$ addAction(ControlElement.ACTION, _value.getString()); break; case 7 : if(_value.getObject() instanceof java.text.DecimalFormat) { if(format==(java.text.DecimalFormat) _value.getObject()) { return; } format = (java.text.DecimalFormat) _value.getObject(); titledBorder.setTitle(format.format(internalValue.value)); slider.setBorder(titledBorder); } break; case 8 : if(_value.getInteger()!=ticks) { ticks = _value.getInteger(); setTicks(); } break; case 9 : if(_value.getObject() instanceof java.text.DecimalFormat) { if(ticksFormat==(java.text.DecimalFormat) _value.getObject()) { return; } ticksFormat = (java.text.DecimalFormat) _value.getObject(); slider.setPaintLabels(true); setTicks(); } break; case 10 : slider.setSnapToTicks(_value.getBoolean()); break; case 11 : if(slider.getOrientation()!=_value.getInteger()) { slider.setOrientation(_value.getInteger()); } break; default : super.setValue(_index-12, _value); break; } } public void setDefaultValue(int _index) { switch(_index) { case VARIABLE : break; // Do nothing case 1 : defaultValueSet = false; break; case 2 : setMinimum(0.0); break; case 3 : setMaximum(1.0); break; case 4 : removeAction(ControlSwingElement.ACTION_PRESS, getProperty("pressaction")); //$NON-NLS-1$ break; case 5 : removeAction(ControlElement.VARIABLE_CHANGED, getProperty("dragaction")); //$NON-NLS-1$ break; case 6 : removeAction(ControlElement.ACTION, getProperty("action")); //$NON-NLS-1$ break; case 7 : format = null; slider.setBorder(etchedBorder); break; case 8 : ticks = 0; setTicks(); break; case 9 : ticksFormat = null; slider.setPaintLabels(false); setTicks(); break; case 10 : slider.setSnapToTicks(false); break; case 11 : slider.setOrientation(SwingConstants.HORIZONTAL); break; default : super.setDefaultValue(_index-12); break; } } public Value getValue(int _index) { switch(_index) { case VARIABLE : return internalValue; case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : case 7 : case 8 : case 9 : case 10 : case 11 : return null; default : return super.getValue(_index-12); } } // ------------------------------------- // Private methods // ------------------------------------- private void setTicks() { if(ticks<2) { slider.setPaintTicks(false); return; } int spacing = RESOLUTION/(ticks-1); slider.setMinorTickSpacing(spacing); slider.setMajorTickSpacing(2*spacing); slider.setPaintTicks(true); if(ticksFormat!=null) { java.util.Hashtable<Integer, JLabel> table = new java.util.Hashtable<Integer, JLabel>(); for(int i = 0; i<=RESOLUTION; i += 2*spacing) { table.put(new Integer(i), new javax.swing.JLabel(ticksFormat.format(minimum+i/scale))); } slider.setLabelTable(table); } } private void setMinimum(double val) { if(val==minimum) { return; } minimum = val; if(minimum>=maximum) { maximum = minimum+1.0; } // internalValue.value = minimum; scale = 1.0*RESOLUTION/(maximum-minimum); setTicks(); setTheValue(internalValue.value); } private void setMaximum(double val) { if(val==maximum) { return; } maximum = val; if(minimum>=maximum) { minimum = maximum-1.0; } // internalValue.value = minimum; scale = 1.0*RESOLUTION/(maximum-minimum); setTicks(); setTheValue(internalValue.value); } // ------------------------------------- // Inner classes // ------------------------------------- private class MyChangeListener implements javax.swing.event.ChangeListener { public void stateChanged(javax.swing.event.ChangeEvent e) { if(recalculate) { double value = minimum+slider.getValue()/scale; // if (internalValue.value==value) return; internalValue.value = value; if(format!=null) { titledBorder.setTitle(format.format(internalValue.value)); slider.repaint(); } variableChanged(VARIABLE, internalValue); } } } private class MyMouseListener extends java.awt.event.MouseAdapter { public void mousePressed(java.awt.event.MouseEvent evt) { invokeActions(ControlSwingElement.ACTION_PRESS); } public void mouseReleased(java.awt.event.MouseEvent evt) { invokeActions(ControlElement.ACTION); } } } // End of class /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */