/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
* Corporate:
* Astrium SAS
* EADS CRC
* Individual:
* Nicolas Brodu
*
* $Id: RangeSource.java,v 1.3 2007/01/23 17:10:38 ogor Exp $
*
* Changes
* -------
* 22-Jan-2004 : Creation date (NB);
*
*/
package jsynoptic.builtin;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.util.ResourceBundle;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import jsynoptic.data.DataSourceAnimator;
import simtools.data.DataException;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.NoSuchIndex;
import simtools.data.UnsupportedOperation;
import simtools.data.ValueProvider;
import simtools.ui.ActionCheckBox;
import simtools.ui.BasicMessageWriter;
import simtools.ui.ResourceFinder;
import simtools.util.NumberStringComparator;
/**
* This data source produces all the values in a given range, and can work either on "integers"
* or "real" numbers
* The range may be infinite
*/
public class RangeSource extends DataSource {
public static final String ID_PREFIX = "RangeSource:";
public static ResourceBundle resources = ResourceFinder.get(RangeSource.class);
public static BasicMessageWriter messages = ResourceFinder.getMessages(RangeSource.class);
// interval boundaries and step for the range
// in either double or long type
protected double dminValue, dmaxValue, dstep;
protected long lminValue, lmaxValue, lstep;
int kind;
protected DataInfo info;
/* (non-Javadoc)
* @see simtools.data.ValueProvider#getKind()
*/
public int getKind() {
return kind;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getInformation()
*/
public DataInfo getInformation() {
return info;
}
public RangeSource(String name, double minValue, double maxValue, double step) {
dminValue = minValue;
dmaxValue = maxValue;
dstep = step;
kind = ValueProvider.DoubleProvider;
info = new DataInfo(name, ID_PREFIX+name);
Object[] msgParams = new Object[] {new Double(minValue), new Double(maxValue), new Double(step)};
info.comment = messages.printNargs("commentDouble", msgParams);
}
public RangeSource(String name, long minValue, long maxValue, long step) {
lminValue = minValue;
lmaxValue = maxValue;
lstep = step;
kind = ValueProvider.LongProvider;
info = new DataInfo(name, ID_PREFIX+name);
Object[] msgParams = new Object[] {new Long(minValue), new Long(maxValue), new Long(step)};
info.comment = messages.printNargs("commentLong", msgParams);
}
public Object getValue(long index) throws DataException {
// Optimize the code by not wrapping into an object when calling the Double function
if (kind==ValueProvider.DoubleProvider)
return new Double(getDoubleValue(index));
else
return new Double(getLongValue(index));
}
/* (non-Javadoc)
* @see simtools.data.ValueProvider#getDoubleValue(long)
*/
public double getDoubleValue(long index) throws DataException {
if (kind==ValueProvider.LongProvider) return (double)getLongValue(index);
double ret = dminValue + index * dstep;
if ((dstep>0) && (ret>dmaxValue)) throw new NoSuchIndex(index);
if ((dstep<0) && (ret<dmaxValue)) throw new NoSuchIndex(index);
return ret;
}
public long getLongValue(long index) throws DataException {
if (kind==ValueProvider.DoubleProvider) return (long)getDoubleValue(index);
long ret = lminValue + index * lstep;
if ((lstep>0) && (ret>lmaxValue)) throw new NoSuchIndex(index);
if ((lstep<0) && (ret<lmaxValue)) throw new NoSuchIndex(index);
return ret;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#computeLastIndex()
*/
public long computeLastIndex() throws UnsupportedOperation {
return getLastIndex();
}
/* (non-Javadoc)
* @see simtools.data.DataSource#computeStartIndex()
*/
public long computeStartIndex() throws UnsupportedOperation {
return 0;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getLastIndex()
*/
public long getLastIndex() throws UnsupportedOperation {
if (kind==ValueProvider.DoubleProvider)
return dstep==0 ? Long.MAX_VALUE : (long)((dmaxValue-dminValue)/dstep);
else
return lstep==0 ? Long.MAX_VALUE : (long)((lmaxValue-lminValue)/lstep);
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getStartIndex()
*/
public long getStartIndex() throws UnsupportedOperation {
return 0;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#computeMax()
*/
public Object computeMax() {
return getMax();
}
/* (non-Javadoc)
* @see simtools.data.DataSource#computeMin()
*/
public Object computeMin() {
return getMin();
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getDoubleMax()
*/
public double getDoubleMax() {
if (kind==ValueProvider.LongProvider) return lmaxValue;
return dmaxValue;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getDoubleMin()
*/
public double getDoubleMin() {
if (kind==ValueProvider.LongProvider) return lminValue;
return dminValue;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getLongMax()
*/
public long getLongMax() {
if (kind==ValueProvider.DoubleProvider) return (long)dmaxValue;
return lmaxValue;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getLongMin()
*/
public long getLongMin() {
if (kind==ValueProvider.DoubleProvider) return (long)dminValue;
return lminValue;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getMax()
*/
public Object getMax() {
if (kind==ValueProvider.DoubleProvider)
return new Double(getDoubleMax());
else
return new Long(getLongMax());
}
/* (non-Javadoc)
* @see simtools.data.DataSource#getMin()
*/
public Object getMin() {
if (kind==ValueProvider.DoubleProvider)
return new Double(getDoubleMin());
else
return new Long(getLongMin());
}
public Number getStep() {
if (kind==ValueProvider.DoubleProvider)
return new Double(dstep);
else
return new Long(lstep);
}
public static class OptionPanel extends JPanel {
protected JRadioButton rbStatic, rbDynamic;
protected JTextField tfMin, tfMax, tfStep, tfSize, tfPeriod;
protected JLabel bufferLabel;
protected JTextField tfInit;
protected JTextField tfDynaStep;
protected ActionCheckBox cbDynaEnd;
protected JTextField tfDynaStop;
public OptionPanel() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Box box = Box.createHorizontalBox();
box.add(rbStatic = new JRadioButton(resources.getString("static"),true));
box.add(Box.createHorizontalGlue());
add(box);
box = Box.createHorizontalBox();
box.add(rbDynamic = new JRadioButton(resources.getString("dynamic"),false));
box.add(Box.createHorizontalGlue());
add(box);
ButtonGroup bg = new ButtonGroup();
bg.add(rbStatic);
bg.add(rbDynamic);
final JPanel cardPane = new JPanel(new CardLayout());
Box vbox = Box.createVerticalBox();
box = Box.createHorizontalBox();
box.add(new JLabel(" "));
vbox.add(box);
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("min")));
box.add(Box.createHorizontalGlue());
box.add(tfMin = new JTextField());
vbox.add(box);
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("max")));
box.add(Box.createHorizontalGlue());
box.add(tfMax = new JTextField());
vbox.add(box);
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("step")));
box.add(Box.createHorizontalGlue());
box.add(tfStep = new JTextField());
vbox.add(box);
box = Box.createHorizontalBox();
box.add(new JLabel(" "));
vbox.add(box);
cardPane.add(vbox,"s");
vbox = Box.createVerticalBox();
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("initValue")));
box.add(Box.createHorizontalGlue());
box.add(tfInit = new JTextField());
vbox.add(box);
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("step")));
box.add(Box.createHorizontalGlue());
box.add(tfDynaStep = new JTextField());
vbox.add(box);
box = Box.createHorizontalBox();
box.add(cbDynaEnd = new ActionCheckBox(resources.getString("stopValue"), false) {
public void actionPerformed(ActionEvent e) {
tfDynaStop.setEnabled(cbDynaEnd.isSelected());
tfDynaStop.setEditable(cbDynaEnd.isSelected());
}
});
box.add(Box.createHorizontalGlue());
box.add(tfDynaStop = new JTextField());
vbox.add(box);
cbDynaEnd.apply();
box = Box.createHorizontalBox();
box.add(bufferLabel = new JLabel(resources.getString("dynamicBufferLabel")));
box.add(Box.createHorizontalGlue());
box.add(tfSize = new JTextField());
tfSize.setText("100");
vbox.add(box);
box = Box.createHorizontalBox();
box.add(bufferLabel = new JLabel(resources.getString("period")));
box.add(Box.createHorizontalGlue());
box.add(tfPeriod = new JTextField());
tfPeriod.setText("1000");
vbox.add(box);
cardPane.add(vbox,"d");
add(cardPane);
rbDynamic.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
((CardLayout)cardPane.getLayout()).show(cardPane,rbDynamic.isSelected()?"d":"s");
}
});
}
public DataSource createSource(String name) {
DataSource ds;
if (rbDynamic.isSelected()) {
Number i = NumberStringComparator.stringToNumber(tfInit.getText());
if (i==null) i = new Long(0);
Number s = NumberStringComparator.stringToNumber(tfDynaStep.getText());
if (s==null) s = new Long(1);
Number e = cbDynaEnd.isSelected() ? NumberStringComparator.stringToNumber(tfDynaStop.getText()) : null;
boolean useLong = (i instanceof Long) && (s instanceof Long) && ((e==null) || (e instanceof Long));
Number buf = NumberStringComparator.stringToNumber(tfSize.getText());
Number period = NumberStringComparator.stringToNumber(tfPeriod.getText());
if (buf==null) buf = new Long(0);
if (useLong) {
long step = s.longValue();
long max = (e!=null) ? e.longValue() : ( (step>0) ? Long.MAX_VALUE : Long.MIN_VALUE );
if (period==null) ds = new DataSourceAnimator(new RangeSource(name, i.longValue(), max, step), buf.intValue());
else ds = new DataSourceAnimator(new RangeSource(name, i.longValue(), max, step), buf.intValue(), period.intValue());
} else {
double step = s.doubleValue();
double max = (e!=null) ? e.doubleValue() : ( (step>0) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY );
if (period==null) ds = new DataSourceAnimator(new RangeSource(name, i.doubleValue(), max, step), buf.intValue());
else ds = new DataSourceAnimator(new RangeSource(name, i.doubleValue(), max, step), buf.intValue(), period.intValue());
}
} else {
Number min = NumberStringComparator.stringToNumber(tfMin.getText());
if (min==null) min = new Long(0);
Number max = NumberStringComparator.stringToNumber(tfMax.getText());
if (max==null) max = new Long(0);
Number step = NumberStringComparator.stringToNumber(tfStep.getText());
if (step==null) step = new Long(1);
boolean useLong = (min instanceof Long) && (max instanceof Long) && (step instanceof Long);
if (useLong)
ds = new RangeSource(name, min.longValue(), max.longValue(), step.longValue());
else
ds = new RangeSource(name, min.doubleValue(), max.doubleValue(), step.doubleValue());
}
return ds;
}
}
/* (non-Javadoc)
* @see simtools.data.DataSource#isComparable()
*/
public boolean isComparable() {
return true;
}
/* (non-Javadoc)
* @see simtools.data.DataSource#sortedOrder()
*/
public int sortedOrder() {
if (kind==ValueProvider.LongProvider) {
if (lminValue < lmaxValue) return 1;
if (lmaxValue < lminValue) return -1;
}
else if (kind==ValueProvider.DoubleProvider) {
if (dminValue < dmaxValue) return 1;
if (dmaxValue < dminValue) return -1;
}
return 0;
}
/* (non-Javadoc)
* @see simtools.data.ValueProvider#valueClass()
*/
public Class valueClass() {
if (kind==ValueProvider.LongProvider) return Long.class;
else if (kind==ValueProvider.DoubleProvider) return Double.class;
return Object.class; // error
}
}