/*
* ErrorBarPolicyRelative.java of project jchart2d, configurable
* info.monitorenter.gui.chart.IErrorBarPolicy that adds a
* relative error to the points to render.
* Copyright (c) 2007 - 2011 Achim Westermann, created on 10.08.2006 19:37:54.
*
* This library 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 library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*
* If you modify or optimize the code in a useful way please let me know.
* Achim.Westermann@gmx.de
*
*/
package info.monitorenter.gui.chart.errorbars;
import info.monitorenter.gui.chart.IErrorBarPolicy;
import info.monitorenter.gui.chart.ITracePoint2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Configurable <code>{@link info.monitorenter.gui.chart.IErrorBarPolicy}</code>
* that adds a relative error (relative to the absolute values) to the points to
* render.
* <p>
*
* You should not use this if you have a small value range but very high values:
* The relative value will cause exteremely long lines (be much higher than the
* value range to display) and fold the trace to a minimum line.
* <p>
*
* @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann</a>
*
*
* @version $Revision: 1.23 $
*/
public class ErrorBarPolicyRelative extends AErrorBarPolicyConfigurable {
/** Generated <code>serialVersionUID</code>. */
private static final long serialVersionUID = 1031825382468141565L;
/** The relative x error to render. */
private double m_relativeXError = 0.02;
/** The relative y error to render. */
private double m_relativeYError = 0.02;
/**
* Creates an instance with the given relative errors.
* <p>
*
* The relative error is related to the absolut x and y values to render. It
* has to be between 0.0 and 1.0.
* <p>
*
* @param relativeError
* the relative error value between 0.0 and 1.0 for x and y
* dimension.
*
* @throws IllegalArgumentException
* if the argument is not between 0.0 and 1.0.
*
* @see #ErrorBarPolicyRelative(double, double)
*/
public ErrorBarPolicyRelative(final double relativeError) throws IllegalArgumentException {
this(relativeError, relativeError);
}
/**
* Creates an instance with the given relative errors.
* <p>
*
* The relative error is related to the absolut x and y values to render. It
* has to be between 0.0 and 1.0.
* <p>
*
* @param relativeXError
* the relative x error value between 0.0 and 1.0.
*
* @param relativeYError
* the relative y error value between 0.0 and 1.0.
*
* @throws IllegalArgumentException
* if the argument is not between 0.0 and 1.0.
*/
public ErrorBarPolicyRelative(final double relativeXError, final double relativeYError)
throws IllegalArgumentException {
this.setRelativeXError(relativeXError);
this.setRelativeYError(relativeYError);
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final ErrorBarPolicyRelative other = (ErrorBarPolicyRelative) obj;
if (Double.doubleToLongBits(this.m_relativeXError) != Double
.doubleToLongBits(other.m_relativeXError)) {
return false;
}
if (Double.doubleToLongBits(this.m_relativeYError) != Double
.doubleToLongBits(other.m_relativeYError)) {
return false;
}
return true;
}
/**
* @see info.monitorenter.gui.chart.errorbars.AErrorBarPolicyConfigurable#getCustomConfigurator()
*/
@Override
public JComponent getCustomConfigurator() {
final JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setLayout(new GridBagLayout());
final GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 0;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
final JLabel xErrorLable = new JLabel("Relative X error (%) ");
panel.add(xErrorLable, gbc);
final SpinnerModel numberXModel = new SpinnerNumberModel(ErrorBarPolicyRelative.this
.getRelativeXError() * 100, 0, 100, 1);
final JSpinner xErrorSelector = new JSpinner(numberXModel);
gbc.gridx = 1;
gbc.weightx = 0.5;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(xErrorSelector, gbc);
// fill a dummy component that may be resized:
gbc.gridx = 2;
gbc.gridheight = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
panel.add(Box.createHorizontalGlue(), gbc);
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0;
final JLabel yErrorLable = new JLabel("Relative Y error (%) ");
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridheight = 1;
panel.add(yErrorLable, gbc);
final SpinnerModel numberYModel = new SpinnerNumberModel(ErrorBarPolicyRelative.this
.getRelativeYError() * 100, 0, 100, 1);
final JSpinner yErrorSelector = new JSpinner(numberYModel);
gbc.gridx = 1;
gbc.weightx = 0.5;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(yErrorSelector, gbc);
// actions:
xErrorSelector.addChangeListener(new ChangeListener() {
public void stateChanged(final ChangeEvent e) {
final JSpinner spinner = (JSpinner) e.getSource();
final SpinnerNumberModel model = (SpinnerNumberModel) spinner.getModel();
final Number number = model.getNumber();
ErrorBarPolicyRelative.this.setRelativeXError(number.doubleValue() / 100);
}
});
yErrorSelector.addChangeListener(new ChangeListener() {
public void stateChanged(final ChangeEvent e) {
final JSpinner spinner = (JSpinner) e.getSource();
final SpinnerNumberModel model = (SpinnerNumberModel) spinner.getModel();
final Number number = model.getNumber();
ErrorBarPolicyRelative.this.setRelativeYError(number.doubleValue() / 100);
}
});
return panel;
}
/**
* Returns the relative x error between 0 and 1.
* <p>
*
* @return the relative x error.
*/
public final double getRelativeXError() {
return this.m_relativeXError;
}
/**
* Returns the relative y error between 0 and 1.
* <p>
*
* @return the relative y Error.
*/
public final double getRelativeYError() {
return this.m_relativeYError;
}
/**
* @see info.monitorenter.gui.chart.IErrorBarPolicy#getXError(double)
*/
public final double getXError(final double xValue) {
return this.m_relativeXError * xValue;
}
/**
* @see info.monitorenter.gui.chart.IErrorBarPolicy#getYError(double)
*/
public final double getYError(final double yValue) {
return this.m_relativeYError * yValue;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(this.m_relativeXError);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(this.m_relativeYError);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
/**
* @see info.monitorenter.gui.chart.errorbars.AErrorBarPolicyConfigurable#internalGetNegativeXError(int,
* int, info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected int internalGetNegativeXError(final int xPixel, final int yPixel,
final ITracePoint2D original) {
final double error = (xPixel - this.getTrace().getRenderer().getXChartStart())
* this.m_relativeXError;
final int result = (int) Math.round(xPixel - error);
return result;
}
/**
* @see info.monitorenter.gui.chart.errorbars.AErrorBarPolicyConfigurable#internalGetNegativeYError(int,
* int, info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected int internalGetNegativeYError(final int xPixel, final int yPixel,
final ITracePoint2D original) {
final int error = (int) Math.round((this.getTrace().getRenderer().getYChartStart() - yPixel)
* this.m_relativeYError);
return yPixel + error;
}
/**
* @see info.monitorenter.gui.chart.errorbars.AErrorBarPolicyConfigurable#internalGetPositiveXError(int,
* int, info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected int internalGetPositiveXError(final int xPixel, final int yPixel,
final ITracePoint2D original) {
final double error = (xPixel - this.getTrace().getRenderer().getXChartStart())
* this.m_relativeXError;
final int result = (int) Math.round(xPixel + error);
return result;
}
/**
* @see info.monitorenter.gui.chart.errorbars.AErrorBarPolicyConfigurable#internalGetPositiveYError(int,
* int, info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected int internalGetPositiveYError(final int xPixel, final int yPixel,
final ITracePoint2D original) {
// y pixel are bigger the lower the value is, so inversion
// is needed here:
final int error = (int) Math.round((this.getTrace().getRenderer().getYChartStart() - yPixel)
* this.m_relativeYError);
return yPixel - error;
}
/**
* Sets the relative X error to add to each error bar.
* <p>
*
* The relative error is related to the absolute x values to render. It has to
* be between 0.0 and 1.0.
* <p>
*
* @param relativeXError
* a value between 0.0 and 1.0.
*
* @throws IllegalArgumentException
* if the argument is not between 0.0 and 1.0.
*/
public final void setRelativeXError(final double relativeXError) throws IllegalArgumentException {
if ((relativeXError <= 0.0) || (relativeXError >= 1.0)) {
throw new IllegalArgumentException("Given relative error (" + relativeXError
+ ")has to be between 0.0 and 1.0.");
}
final boolean change = this.m_relativeXError != relativeXError;
if (change) {
this.m_relativeXError = relativeXError;
this.firePropertyChange(IErrorBarPolicy.PROPERTY_CONFIGURATION, null, null);
}
}
/**
* Sets the relative Y error to add to each error bar.
* <p>
*
* The relative error is related to the absolut y values to render. It has to
* be between 0.0 and 1.0.
* <p>
*
* @param relativeYError
* a value between 0.0 and 1.0.
*
* @throws IllegalArgumentException
* if the argument is not between 0.0 and 1.0.
*/
public final void setRelativeYError(final double relativeYError) throws IllegalArgumentException {
if ((relativeYError <= 0.0) || (relativeYError >= 1.0)) {
throw new IllegalArgumentException("Given relative error (" + relativeYError
+ ")has to be between 0.0 and 1.0.");
}
final boolean change = this.m_relativeYError != relativeYError;
if (change) {
this.m_relativeYError = relativeYError;
this.firePropertyChange(IErrorBarPolicy.PROPERTY_CONFIGURATION, null, null);
}
}
}