/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.util.media.chart;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
import java.util.*;
import sim.util.gui.*;
// From JFreeChart (jfreechart.org)
import org.jfree.data.xy.*;
import org.jfree.chart.*;
import org.jfree.chart.event.*;
import org.jfree.chart.plot.*;
import org.jfree.data.general.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.general.*;
/** A SeriesAttributes used for user control of histogram series created with HistogramGenerator.
Unfortunately JFreeChart doesn't have nearly
as well-designed a histogram chart facility as its time series charts. There is no HistogramSeries object to
encapsulate a series, and no facilities for deleting or moving series relative to one another.
*/
public class HistogramSeriesAttributes extends SeriesAttributes
{
/** Border thickness */
float thickness;
NumberTextField thicknessField;
/** Whether or not to include the margin as a GUI option. */
boolean includeMargin;
/** The margin: the percentage of available space that a histogram bar will actually take up.
Turned off by default. */
float margin;
NumberTextField marginField;
/** The color of the histogram bar. */
Color fillColor;
ColorWell fillColorWell;
/** The color of the histogram bar border. */
Color strokeColor;
ColorWell strokeColorWell;
/** The opacity of the histogram bar. Sadly this must be separate than the color because
Sun doesn't have a proper color selector. */
double fillOpacity;
NumberTextField fillOpacityField;
/** The opacity of the histogram bar border. Sadly this must be separate than the color because
Sun doesn't have a proper color selector. */
double lineOpacity;
NumberTextField lineOpacityField;
NumberTextField numBinsField;
public void setFillOpacity(double value) { fillOpacityField.setValue(fillOpacityField.newValue(value)); }
public double getFillOpacity() { return fillOpacityField.getValue(); }
public void setLineOpacity(double value) { lineOpacityField.setValue(lineOpacityField.newValue(value)); }
public double getLineOpacity() { return lineOpacityField.getValue(); }
public void setThickness(float value) { thicknessField.setValue(thicknessField.newValue(value)); }
public float getThickness() { return (float)(thicknessField.getValue()); }
public void setMargin(float value) { marginField.setValue(marginField.newValue(value)); }
public float getMargin() { return (float)(marginField.getValue()); }
public void setNumBins(int value) { numBinsField.setValue(numBinsField.newValue(value)); }
public int getNumBins() { return (int)(numBinsField.getValue()); }
public void setFillColor(Color value) { fillColorWell.changeColor(fillColor = value); }
public Color getFillColor() { return fillColor; }
public void setStrokeColor(Color value) { strokeColorWell.changeColor(strokeColor = value); }
public Color getStrokeColor() { return strokeColor; }
/** Produces a HistogramSeriesAttributes object with the given generator, series name, series index,
and desire to display margin options. */
public HistogramSeriesAttributes(ChartGenerator generator, String name, int index, boolean includeMargin)
{
super(generator, name, index);
setName(name);//I need this for the remove series confirmation dialog.
this.includeMargin = includeMargin;
}
public void setSeriesName(String val)
{
setName(val);
((HistogramGenerator)generator).updateName(seriesIndex,val,false);
}
public String getSeriesName() { return getName(); }
public void rebuildGraphicsDefinitions()
{
XYBarRenderer renderer = (XYBarRenderer)getRenderer();
if (thickness == 0.0)
renderer.setDrawBarOutline(false);
else
{
renderer.setSeriesOutlineStroke(getSeriesIndex(),
new BasicStroke(thickness));
renderer.setDrawBarOutline(true);
}
renderer.setSeriesPaint(getSeriesIndex(),reviseColor(fillColor, fillOpacity));
renderer.setSeriesOutlinePaint(getSeriesIndex(),reviseColor(strokeColor, lineOpacity));
if (includeMargin) renderer.setMargin(margin);
repaint();
}
public void buildAttributes()
{
// The following three variables aren't defined until AFTER construction if
// you just define them above. So we define them below here instead.
thickness = 2.0f;
margin = 0.5f;
fillOpacity = 1.0;
lineOpacity = 1.0;
numBinsField = new NumberTextField("", ((HistogramGenerator)generator).getNumBins(seriesIndex),true)
{
public double newValue(double newValue)
{
newValue = (int)newValue;
if (newValue < 1)
newValue = currentValue;
((HistogramGenerator)generator).updateSeries(seriesIndex, (int)newValue, false);
rebuildGraphicsDefinitions(); // forces a repaint
return newValue;
}
};
addLabelled("Bins",numBinsField);
// fillColor = (Color)(getRenderer().getSeriesPaint(getSeriesIndex()));
// this returns null, cause getSeriesPaint returns whatever was set through setSeriesPaint;
// for the default colors, you need "lookupSeriesPaint()".
//fillColor = (Color) (getRenderer().lookupSeriesPaint(getSeriesIndex()));
// getRenderer returns an object implementing the XYItemRenderer interface.
// either you cast that object to AbstractRenderer, and call lookupSeriesPaint()
// or you call getItemPaint() on it directly; all getItemPaint does is call lookupSeriesPaint(),
// but that looks bad, cause getItemPaint() seems to be meant for category data).
//On the other hand, lookupSeriesPaint() does not show up before 1.0.6, so
// in the interest of backward compatibility:
fillColor = (Color) (getRenderer().getItemPaint(getSeriesIndex(), -1));
// second argument does not matter
fillColor = (Color)(getRenderer().getSeriesPaint(getSeriesIndex()));
fillColorWell = new ColorWell(fillColor)
{
public Color changeColor(Color c)
{
fillColor = c;
rebuildGraphicsDefinitions();
return c;
}
};
addLabelled("Fill",fillColorWell);
fillOpacityField = new NumberTextField("Opacity ", fillOpacity,1.0,0.125)
{
public double newValue(double newValue)
{
if (newValue < 0.0 || newValue > 1.0)
newValue = currentValue;
fillOpacity = (float)newValue;
rebuildGraphicsDefinitions();
return newValue;
}
};
addLabelled("",fillOpacityField);
strokeColor = Color.black; //(Color)(getRenderer().getSeriesOutlinePaint(getSeriesIndex()));
strokeColorWell = new ColorWell(strokeColor)
{
public Color changeColor(Color c)
{
strokeColor = c;
rebuildGraphicsDefinitions();
return c;
}
};
addLabelled("Line",strokeColorWell);
lineOpacityField = new NumberTextField("Opacity ", lineOpacity,1.0,0.125)
{
public double newValue(double newValue)
{
if (newValue < 0.0 || newValue > 1.0)
newValue = currentValue;
lineOpacity = (float)newValue;
rebuildGraphicsDefinitions();
return newValue;
}
};
addLabelled("",lineOpacityField);
thicknessField = new NumberTextField(thickness,false)
{
public double newValue(double newValue)
{
if (newValue < 0.0)
newValue = currentValue;
thickness = (float)newValue;
rebuildGraphicsDefinitions();
return newValue;
}
};
addLabelled("Width",thicknessField);
if (includeMargin)
{
marginField = new NumberTextField(0.5,1.0,0.125)
{
public double newValue(double newValue)
{
if (newValue < 0.0 || newValue > 1.0)
newValue = currentValue;
margin = (float)newValue;
rebuildGraphicsDefinitions();
return newValue;
}
};
addLabelled("Space",marginField);
}
}
}