blob: cd5f5cf72adbad6159bcaf9089f5ec65eff27718 [file] [log] [blame]
package org.eclipse.stem.analysis.automaticexperiment.views;
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.factory.Generator;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.ChartWithAxes;
import org.eclipse.birt.chart.model.attribute.Anchor;
import org.eclipse.birt.chart.model.attribute.AxisType;
import org.eclipse.birt.chart.model.attribute.Bounds;
import org.eclipse.birt.chart.model.attribute.ColorDefinition;
import org.eclipse.birt.chart.model.attribute.IntersectionType;
import org.eclipse.birt.chart.model.attribute.LineAttributes;
import org.eclipse.birt.chart.model.attribute.LineStyle;
import org.eclipse.birt.chart.model.attribute.Position;
import org.eclipse.birt.chart.model.attribute.TickStyle;
import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.birt.chart.model.component.Axis;
import org.eclipse.birt.chart.model.component.Series;
import org.eclipse.birt.chart.model.component.impl.SeriesImpl;
import org.eclipse.birt.chart.model.data.NumberDataSet;
import org.eclipse.birt.chart.model.data.SeriesDefinition;
import org.eclipse.birt.chart.model.data.impl.NumberDataElementImpl;
import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl;
import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl;
import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl;
import org.eclipse.birt.chart.model.layout.Legend;
import org.eclipse.birt.chart.model.layout.Plot;
import org.eclipse.birt.chart.model.type.LineSeries;
import org.eclipse.birt.chart.model.type.impl.ScatterSeriesImpl;
import org.eclipse.birt.chart.util.PluginSettings;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.stem.analysis.automaticexperiment.Activator;
import org.eclipse.stem.ui.preferences.VisualizationPreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IWorkbenchActionConstants;
/**
* AggregateTimeSeriesCanvas is a subclass of {@link Canvas} suitable for chart drawings.
*/
public class AggregateTimeSeriesCanvas extends Canvas {
protected IDeviceRenderer idr = null;
/**
* This is the {@link Chart} that plots the relative values.
*/
protected Chart cm = null;
/**
* The provider of relative values.
*/
//private RelativeValueHistoryProvider rvhp;
private AnalysisControl control = null;
/**
* the index of this Chart
*/
private int chartIndex = 0;
/**
* some extra colors
*/
protected static final ColorDefinition[] colorDefault = {
ColorDefinitionImpl.RED(),
ColorDefinitionImpl.GREEN(),
ColorDefinitionImpl.BLUE(),
ColorDefinitionImpl.BLACK(),
ColorDefinitionImpl.GREY(),
ColorDefinitionImpl.CYAN(),
ColorDefinitionImpl.ORANGE()
};
/**
* used if we need to overlay traces in different colors
*/
private boolean overlayMode = false;
/**
* A context menu for this view
*/
Menu popUpMenu = null;
/**
* set y axis to a linear scale
*/
private LinearScaleAction linearTimeAction;
/**
* set y axis to a log scale
*/
private LogScaleAction logTimeAction;
protected boolean useLinearTimeScale = true;
/**
* show the legend (true by default)
*/
private LegendViewAction viewLegend;
/**
* hide the legend
*/
private LegendHideAction hideLegend;
protected boolean showLegend = true;
protected Legend legend = null;
/**
* this is a map of the DataSeries object (keyed by property name)
*/
protected final Map<String,DataSeries> dataSeriesMap = new HashMap<String,DataSeries>();
/**
* Keep track of which timeseries are visible
*/
protected Map<String, Boolean>visibleMap = new HashMap<String,Boolean>();
/**
* These are the cycle numbers that match the relative values that will be
* plotted
*
* @see #relativeValues
*/
private final List<Integer> cycleNumbers = new ArrayList<Integer>();
/**
* Chart generator instance (reference to a singleton)
*/
Generator gr;
Axis yAxisPrimary;
Axis xAxisPrimary;
/**
* the maxY value for scaling
*/
double maxY = -1.0;
/**
* Log of zero is negative infinity so for each location we will cut off the minimum
* at the min NONZERO Y value
*/
private double minYscale = 1.0;
/**
* Label for line series LEGEND
*/
public String Ordinate_LEGEND = "Y";
/**
* Label for line series Y axis label
**/
public String Ordinate_AXIS = "Y";
/**
* Label for line series X axis label
**/
public String X_AXIS = "X";
/**
* customizable color definitions
*/
private ColorDefinition foreGround = ColorDefinitionImpl.WHITE();
private ColorDefinition backgroundGround = ColorDefinitionImpl.BLACK();
private ColorDefinition frameColor = ColorDefinitionImpl.create(180, 180, 200);
Image imgChart = null;
/**
* This Constructor is used when we want to place the time series in a container
* which is a sub component of the actual AnalysisControl
* @param analysisControl
*
* @param parent the SWT parent of the {@link Widget}
* @param ordinateString
* @param yAxisLabel
* @param xAxisLabel
* @param foreground
* @param background
* @param framecolor
* @param chartIndex the index of this chart (0 if only one)
* @param overlayMode used if we need to overlay traces in different colors
*/
public AggregateTimeSeriesCanvas(final AnalysisControl analysisControl, final Composite parent,
final String ordinateString,
final String yAxisLabel,
final String xAxisLabel,
final String firstProperty,
ColorDefinition foreground,
ColorDefinition background,
ColorDefinition framecolor,
int chartIndex,
boolean overlayMode ) {
super(parent, SWT.DOUBLE_BUFFERED | SWT.BORDER);
Ordinate_LEGEND = ordinateString;
Ordinate_AXIS = yAxisLabel;
X_AXIS = xAxisLabel;
foreGround = foreground;
backgroundGround = background;
frameColor = framecolor;
this.chartIndex = chartIndex;
this.overlayMode = overlayMode;
gr = Generator.instance();
try {
idr = PluginSettings.instance().getDevice("dv.SWT"); //$NON-NLS-1$
} catch (final ChartException pex) {
Activator.logError("Problem initializing chart", pex); //$NON-NLS-1$
return;
}
control = analysisControl;
cm = createSimpleLineChart(firstProperty, dataSeriesMap, cycleNumbers, Messages
.getString("CC.title")); //$NON-NLS-1$
resetData();
addPaintListener(new PaintListener() {
public void paintControl(final PaintEvent pe) {
final Composite source = (Composite) pe.getSource();
final org.eclipse.swt.graphics.Rectangle d = source
.getClientArea();
if(imgChart != null) imgChart.dispose();
imgChart = new Image(source.getDisplay(), d);
idr.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, new GC(
imgChart));
final Bounds bounds = BoundsImpl.create(d.x, d.y, d.width,
d.height);
bounds.scale(72d / idr.getDisplayServer().getDpiResolution());
// BOUNDS MUST BE SPECIFIED IN POINTS
try {
gr.render(idr, gr.build(idr.getDisplayServer(), cm, bounds,
null, null, null));
pe.gc.drawImage(imgChart, d.x, d.y);
} catch (final ChartException ce) {
Activator.logError("Problem rendering chart", ce); //$NON-NLS-1$
}
} // paintControl
} // PaintListener
);
//Create a context menu for the canvas
createContextMenu(this);
} // AggregateTimeSeriesCanvas
/**
* Constructor.
*
* @param parent the SWT parent of the {@link Widget}
* @param ordinateString
* @param yAxisLabel
* @param xAxisLabel
* @param foreground
* @param background
* @param framecolor
* @param chartIndex the index of this chart (0 if only one)
*
*/
public AggregateTimeSeriesCanvas(final Composite parent,
final String ordinateString,
final String yAxisLabel,
final String xAxisLabel,
final String firstProperty,
ColorDefinition foreground,
ColorDefinition background,
ColorDefinition framecolor,
int chartIndex) {
super(parent, SWT.DOUBLE_BUFFERED | SWT.BORDER);
Ordinate_LEGEND = ordinateString;
Ordinate_AXIS = yAxisLabel;
X_AXIS = xAxisLabel;
foreGround = foreground;
backgroundGround = background;
frameColor = framecolor;
this.chartIndex = chartIndex;
gr = Generator.instance();
try {
idr = PluginSettings.instance().getDevice("dv.SWT"); //$NON-NLS-1$
} catch (final ChartException pex) {
Activator.logError("Problem initializing chart", pex); //$NON-NLS-1$
return;
}
control = (AnalysisControl) parent;
cm = createSimpleLineChart(firstProperty, dataSeriesMap, cycleNumbers, Messages
.getString("CC.title")); //$NON-NLS-1$
resetData();
addPaintListener(new PaintListener() {
public void paintControl(final PaintEvent pe) {
final Composite source = (Composite) pe.getSource();
final org.eclipse.swt.graphics.Rectangle d = source
.getClientArea();
if(imgChart != null) imgChart.dispose();
imgChart = new Image(source.getDisplay(), d);
idr.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, new GC(
imgChart));
final Bounds bounds = BoundsImpl.create(d.x, d.y, d.width,
d.height);
bounds.scale(72d / idr.getDisplayServer().getDpiResolution());
// BOUNDS MUST BE SPECIFIED IN POINTS
try {
gr.render(idr, gr.build(idr.getDisplayServer(), cm, bounds,
null, null, null));
pe.gc.drawImage(imgChart, d.x, d.y);
} catch (final ChartException ce) {
Activator.logError("Problem rendering chart", ce); //$NON-NLS-1$
}
} // paintControl
} // PaintListener
);
//Create a context menu for the canvas
createContextMenu(this);
} // AggregateTimeSeriesCanvas
/**
* The method which gets the {@link AggregateTimeSeriesCanvas}' reports list, and
* draws it on the {@link AggregateTimeSeriesCanvas}.
* @return integratedDifference for each line series
*
*/
public void draw() {
//clearData();
resetData();
yAxisPrimary.getSeriesDefinitions().clear();
// get the number of lines to plot for this type of chart
int maxLines = control.getNumProperties(chartIndex);
// add all the rest of the line series now
for (int i = 0; i < maxLines; i ++) {
String property = control.getProperty(chartIndex,i);
if(!dataSeriesMap.containsKey(property)) {
// new property
DataSeries series = new DataSeries(property, i, overlayMode);
if(visibleMap.containsKey(property))
series.setVisible(visibleMap.get(property));
else {
series.setVisible(true);
visibleMap.put(property, true);
}
dataSeriesMap.put(property, series);
}
DataSeries series = dataSeriesMap.get(property);
series.show();
}
// update the context menu with the new properties to plot
//updateContextMenu(this);
maxY = -1.0;
boolean setCycles = false;
// Get the values for the property to be plotted
int maxPoints = 0;
for (int i = 0; i < maxLines; i++) {
String property = control.getProperty(chartIndex,i);
double[] doubleValues = control.getValues(chartIndex,i);
if(doubleValues==null) {
doubleValues = new double[0];
//doubleValues[0] = 0;
}
DataSeries series = dataSeriesMap.get(property);
if(dataSeriesMap.get(property).isVisible() == true) {
for (int j = 0; j < doubleValues.length; j++) {
if(doubleValues[j] <= minYscale) {
if(doubleValues[j] > 0.0) minYscale = doubleValues[j];
}
if(doubleValues[j] >= maxY) {
maxY = doubleValues[j];
double log = Math.floor(Math.log10(maxY));
double adjustedMax = (Math.ceil(maxY/Math.pow(10, log)))*Math.pow(10, log);
if(adjustedMax <= 1.0) adjustedMax = 1.0;
//adjustedMax = maxY*100.0;
//adjustedMax += 1.0;
//int mx = (int)adjustedMax;
//adjustedMax = ((double)mx)/100.0;
if (useLinearTimeScale) {
yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(adjustedMax));
double step = adjustedMax / 10.0;
yAxisPrimary.getScale().setStep(step);
} else {
// keep 2 significant figures on scale axis
double ymax = Math.log(adjustedMax);
if(adjustedMax > 1.0) {
ymax += 0.499;
long imax = Math.round(ymax);
ymax = imax;
}
yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(ymax));
double step = ymax/10.0;
yAxisPrimary.getScale().setStep(step);
}
}
}
} // is visible
// Any values?
if (doubleValues.length > 0) {
if (maxPoints < doubleValues.length) {
maxPoints = doubleValues.length;
}
for (int cycleNumber = 0; cycleNumber < doubleValues.length; cycleNumber++) {
Double value;
double displayValue = doubleValues[cycleNumber];
if (displayValue <= minYscale) {
// Log(0.0) is negative infinity so for display purposes only
// we set the minimum axis value at 0.1/POPULATION
displayValue = minYscale;
}
if (useLinearTimeScale) {
value = new Double(displayValue);
} else {
value = new Double(Math.log(displayValue));
}
series.addValue(value);
// only do once for first line series
if (!setCycles) {
cycleNumbers.add(Integer.valueOf(cycleNumber));
}
} // for cycleNumber
if(xAxisPrimary.getSeriesDefinitions().get(0).getSeries().size() != cycleNumbers.size()) {
// The number of data points have changed, create a new series for the x axis
xAxisPrimary.getSeriesDefinitions().clear();
final Series xAxisSeries = SeriesImpl.create();
final NumberDataSet xValues = NumberDataSetImpl.create(cycleNumbers);
xAxisSeries.setDataSet(xValues);
final SeriesDefinition sdX = SeriesDefinitionImpl.create();
xAxisPrimary.getSeriesDefinitions().add(sdX);
sdX.getSeries().add(xAxisSeries);
}
setCycles = true; // we set them only once
} else {
//resetData();
}
} // for i properties
if (!this.isDisposed()) {
redraw();
}
// control.updateMessage(ScenarioAnalysisSuite.WORKING_MSG);
} // paintControl
/**
* @param dataSeriesMap
* the {@link List} that will contain the relative values
* (0.0-1.0) to plot
* @param cycleNumbers
* the {@link List} of simulation cycle numbers that match the
* relative values
* @param seriesIdentifier
* the title of the chart
* @return a <code>Chart</code>
*/
public final Chart createSimpleLineChart(
final String firstProperty,
final Map<String, DataSeries> dataSeriesMap,
final List<Integer> cycleNumbers, final String seriesIdentifier) {
final ChartWithAxes retValue = ChartWithAxesImpl.create();
// Plot
retValue.getBlock().setBackground(frameColor);
final Plot p = retValue.getPlot();
p.getClientArea().setBackground(backgroundGround);
// Title
// cwaLine.getTitle( ).getLabel( ).getCaption( ).setValue( "Line Chart"
// );//$NON-NLS-1$
retValue.getTitle().setVisible(false);
// Legend
legend = retValue.getLegend();
final LineAttributes lia = legend.getOutline();
legend.getText().getFont().setSize(8);
lia.setStyle(LineStyle.SOLID_LITERAL);
legend.getInsets().set(10, 5, 0, 0);
legend.getOutline().setVisible(false);
legend.setAnchor(Anchor.NORTH_LITERAL);
legend.setPosition(Position.BELOW_LITERAL);
legend.getText().setColor(foreGround);
legend.getOutline().setColor(foreGround);
// cwaLine.getLegend( ).getText().getFont().setSize(16);;
// cwaLine.getLegend( ).setVisible( true );
// /////////
// X-Axis
xAxisPrimary = retValue.getPrimaryBaseAxes()[0];
xAxisPrimary.setType(AxisType.TEXT_LITERAL);
xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.BELOW_LITERAL);
xAxisPrimary.getOrigin().setType(IntersectionType.VALUE_LITERAL);
xAxisPrimary.getTitle().setVisible(false);
xAxisPrimary.getTitle().getCaption().getFont().setSize(9);
xAxisPrimary.getTitle().getCaption().setColor(foreGround);
xAxisPrimary.getLabel().getCaption().setColor(foreGround);
final Series xAxisSeries = SeriesImpl.create();
// new colors
xAxisSeries.getLabel().getCaption().setColor(foreGround);
xAxisSeries.getLabel().getOutline().setColor(foreGround);
//
final NumberDataSet xValues = NumberDataSetImpl.create(cycleNumbers);
xAxisSeries.setDataSet(xValues);
final SeriesDefinition sdX = SeriesDefinitionImpl.create();
xAxisPrimary.getSeriesDefinitions().add(sdX);
sdX.getSeries().add(xAxisSeries);
// ////////
// Y-Axis
yAxisPrimary = retValue.getPrimaryOrthogonalAxis(xAxisPrimary);
yAxisPrimary.getMajorGrid().setTickStyle(TickStyle.LEFT_LITERAL);
// NumberDataSet[] orthoValues = new NumberDataSet[MAX_LINES];
// SeriesDefinition[] sdY = new SeriesDefinition[MAX_LINES];
// end Y-Series
xAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0.0));
// xAxisPrimary.getScale( ).setMax( NumberDataElementImpl.create( 10.0 )
// );
// xAxisPrimary.getScale( ).setStep( 1 );
xAxisPrimary.getLabel().getCaption().getFont().setSize(9);
xAxisPrimary.getLabel().getCaption().setColor(foreGround);
xAxisPrimary.getTitle().setVisible(true);
xAxisPrimary.getTitle().getCaption().setValue(X_AXIS);
yAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0.0));
yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(1.0));
yAxisPrimary.getScale().setStep(0.25);
yAxisPrimary.getLabel().getCaption().getFont().setSize(9);
yAxisPrimary.getLabel().getCaption().setColor(foreGround);
yAxisPrimary.getTitle( ).getCaption( ).setValue( Ordinate_AXIS );
yAxisPrimary.getTitle( ).setVisible(true);
// yAxisPrimary.getMajorGrid().getLineAttributes().setColor(foreGround);
// for now get ready to create only one line - we have no data yet.
// we will add more lines as we need them
// handle null
if(!dataSeriesMap.containsKey(firstProperty)) {
DataSeries series = new DataSeries(Messages.getString("AUTO.TITLE4"), 0, overlayMode);
dataSeriesMap.put(firstProperty, series);
}
return retValue;
} // createSimpleLineChart
/**
* Create the view's context menu and add the action handlers to it.
*/
protected void createContextMenu(final Composite parent) {
// Init a Context Menu Manager
final MenuManager contextMenuManager = new MenuManager();
// ---------------------------------------------------------------------
linearTimeAction = new LinearScaleAction();
logTimeAction = new LogScaleAction();
contextMenuManager.add(linearTimeAction);
contextMenuManager.add(logTimeAction);
// Place Holder for Menu Additions
contextMenuManager.add(new Separator(
IWorkbenchActionConstants.MB_ADDITIONS));
// ---------------------------------------------------------------------
viewLegend = new LegendViewAction();
hideLegend = new LegendHideAction();
contextMenuManager.add(viewLegend);
contextMenuManager.add(hideLegend);
// ---------------------------------------------------------------------
// Place Holder for Menu Additions
contextMenuManager.add(new Separator(
IWorkbenchActionConstants.MB_ADDITIONS));
popUpMenu = contextMenuManager.createContextMenu(parent);
// Set the context menu for the viewer
parent.setMenu(popUpMenu);
} // createContextMenu
/**
* Update the view's context menu and add the action handlers to it.
*/
private void updateContextMenu(final Composite parent) {
popUpMenu.dispose();
// Init a Context Menu Manager
final MenuManager contextMenuManager = new MenuManager();
// ---------------------------------------------------------------------
linearTimeAction = new LinearScaleAction();
logTimeAction = new LogScaleAction();
contextMenuManager.add(linearTimeAction);
contextMenuManager.add(logTimeAction);
// ---------------------------------------------------------------------
// Place Holder for Menu Additions
contextMenuManager.add(new Separator(
IWorkbenchActionConstants.MB_ADDITIONS));
// ---------------------------------------------------------------------
viewLegend = new LegendViewAction();
hideLegend = new LegendHideAction();
contextMenuManager.add(viewLegend);
contextMenuManager.add(hideLegend);
// ---------------------------------------------------------------------
// Place Holder for Menu Additions
contextMenuManager.add(new Separator(
IWorkbenchActionConstants.MB_ADDITIONS));
// ---------------------------------------------------------------------
// add the displayable properties
for (int i = 0; i < control.getNumProperties(chartIndex); i ++) {
String nextProp = control.getProperty(chartIndex,i);
DataSeries series = dataSeriesMap.get(nextProp);
DisplayableProperty property = new DisplayableProperty(nextProp, series.isVisible());
contextMenuManager.add(property);
}
// ---------------------------------------------------------------------
// Place Holder for Menu Additions
contextMenuManager.add(new Separator(
IWorkbenchActionConstants.MB_ADDITIONS));
// ---------------------------------------------------------------------
final Menu popUpMenu = contextMenuManager.createContextMenu(parent);
// Set the context menu for the viewer
parent.setMenu(popUpMenu);
} // updateContextMenu
/**
* Sets the colors for a n array of LineSeries given the property to Plot
* for each. Try to set color from the preferences (if specified for that
* property) otherwise sets line color to blue.
*
* @param propertiesToPlot
* @param lsList
*/
public static void setColorDefs(
final List<String> propertiesToPlot,
final List<LineSeries> lsList) {
// the default line color
// if possible get color from preferences
final Map<String, Color> colorMap = VisualizationPreferencePage
.getColorMapping();
for (int i = 0; i < lsList.size(); i++) {
ColorDefinition color = ColorDefinitionImpl.BLUE();
if ((propertiesToPlot != null) && (propertiesToPlot.size() > i)) {
final String key = propertiesToPlot.get(i);
// look or the preference color by name
if (colorMap.containsKey(key)) {
final Color c = colorMap.get(key);
color = ColorDefinitionImpl.create(c.getRed(),
c.getGreen(), c.getBlue());
}
lsList.get(i).setSeriesIdentifier(key);
lsList.get(i).getLineAttributes().setColor(color);
} else {
if (lsList.get(i) != null) {
lsList.get(i).setSeriesIdentifier(" ");
lsList.get(i).getLineAttributes().setColor(color);
}
}
}
return;
}// getColorDef
/**
* Disposes the Color objects
*/
@Override
public void dispose() {
super.dispose();
}
/**
* reset
*/
public void reset() {
resetData();
redraw();
}
protected void resetData() {
clearData();
cycleNumbers.add(Integer.valueOf(0));
}
protected void clearData() {
dataSeriesMap.clear();
cycleNumbers.clear();
}
/**
* toggle the scale from logarithmic to linear
*/
void toggleAxisScale() {
if (useLinearTimeScale) { //Switch to logarithmic scale
logTimeAction.setChecked(true);
linearTimeAction.setChecked(false);
//Just using the following axis type, to move to log scale, didn't work
//yAxisPrimary.setType(AxisType.LOGARITHMIC_LITERAL);
yAxisPrimary.getScale().setMin(null);
yAxisPrimary.getScale().setMax(null);
yAxisPrimary.getScale().unsetStep();
yAxisPrimary.getScale().unsetStepNumber();
}
else { //Switch to linear scale
logTimeAction.setChecked(false);
linearTimeAction.setChecked(true);
//yAxisPrimary.setType(AxisType.LINEAR_LITERAL);
yAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0.0));
yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(1.0));
yAxisPrimary.getScale().setStep(0.25);
}
useLinearTimeScale = !useLinearTimeScale;
draw();
}
/**
* toggle the scale from logarithmic to linear
*/
void toggleLegend() {
if (showLegend) { //Switch to hide
viewLegend.setChecked(false);
hideLegend.setChecked(true);
legend.setVisible(false);
}
else { //Switch to view
viewLegend.setChecked(true);
hideLegend.setChecked(false);
legend.setVisible(true);
}
showLegend = !showLegend;
draw();
}
/**
* Action to show the legend
*/
protected class LegendViewAction extends Action {
public LegendViewAction()
{
super(Messages.getString("ContextMenu.ShowLegend"), IAction.AS_CHECK_BOX);
setChecked(showLegend);
}
/**
* @see org.eclipse.jface.action.Action#getText()
*/
@Override
public String getText() {
return Messages.getString("ContextMenu.ShowLegend");
}
/**
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
if (showLegend) {
setChecked(true);
//Nothing to do. It's already linear-time.
}
else {
toggleLegend();
}
draw();
}
} //LegendViewAction
/**
* Action to hide the legend
*/
class LegendHideAction extends Action {
public LegendHideAction()
{
super(Messages.getString("ContextMenu.HideLegend"), IAction.AS_CHECK_BOX);
setChecked(!showLegend);
}
/**
* @see org.eclipse.jface.action.Action#getText()
*/
@Override
public String getText() {
return Messages.getString("ContextMenu.HideLegend");
}
/**
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
if (!showLegend) {
setChecked(true);
//Nothing to do. It's already log-time.
}
else {
toggleLegend();
}
draw();
}
}//LegendHideAction
/**
* switch to linear plot
*
*/
protected class LinearScaleAction extends Action {
public LinearScaleAction()
{
super(Messages.getString("ContextMenu.LinearTimeScale"), IAction.AS_CHECK_BOX);
setChecked(useLinearTimeScale);
}
/**
* @see org.eclipse.jface.action.Action#getText()
*/
@Override
public String getText() {
return Messages.getString("ContextMenu.LinearTimeScale");
}
/**
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
if (useLinearTimeScale) {
setChecked(true);
//Nothing to do. It's already linear-time.
}
else {
toggleAxisScale();
}
draw();
}
} //LinearScaleAction
/**
* switch to semi-log plot (log scale on y axis)
*
*/
class LogScaleAction extends Action {
public LogScaleAction()
{
super(Messages.getString("ContextMenu.LogTimeScale"), IAction.AS_CHECK_BOX);
setChecked(!useLinearTimeScale);
}
/**
* @see org.eclipse.jface.action.Action#getText()
*/
@Override
public String getText() {
return Messages.getString("ContextMenu.LogTimeScale");
}
/**
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
if (!useLinearTimeScale) {
setChecked(true);
//Nothing to do. It's already log-time.
}
else {
toggleAxisScale();
}
draw();
}
}//LogScaleAction
/**
* DisplayableProperty
*
*/
protected class DisplayableProperty extends Action
{
String property = null;
public DisplayableProperty(String property, boolean visibility)
{
super(property, IAction.AS_CHECK_BOX);
this.property = property;
setChecked(visibility);
}
/**
* @see org.eclipse.jface.action.Action#getText()
*/
@Override
public String getText() {
return property;
}
/**
* Toggle the state
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
DataSeries series = dataSeriesMap.get(property);
series.toggleVisible();
dataSeriesMap.put(property,series);
setChecked(series.isVisible());
visibleMap.put(property, series.isVisible());
draw();
}
}// DisplayableProperty
/**
* Inner class DataSeries
* all the data objects for a plot
*
*/
protected class DataSeries
{
public String propertyName = "";
public List<Double> relativeValues = new ArrayList<Double>();
public Series lineSeries = null;
private boolean visible = true;
private SeriesDefinition sdY = null;
private int seriesIndex = 0;
private boolean overlayMode = false;
public boolean isVisible() {
return visible;
}
public void setVisible(boolean state) {
visible = state;
}
public void toggleVisible() {
visible = !visible;
}
/**
*
* @param propertyName
* @param index
* @param overlay
*/
public DataSeries(String propertyName, int index, boolean overlay) {
this.propertyName = propertyName;
this.seriesIndex = index;
this.overlayMode = overlay;
relativeValues = new ArrayList<Double>();
relativeValues.add(new Double(0.0));
addLineSeries(propertyName);
}
public void addValue(Double val) {
if(relativeValues==null) relativeValues = new ArrayList<Double>();
relativeValues.add(val);
}
/**
* @param propertyName
*
*/
@SuppressWarnings("deprecation")
public void addLineSeries(final String propertyName) {
final NumberDataSet orthoValues = NumberDataSetImpl
.create(relativeValues);
if(lineSeries == null) {
lineSeries = ScatterSeriesImpl.create();
/*
*
* Bar chart style is too slow for generation of a fill
* if we want a fill we can try using the difference plot
* to a straight line at y=0
*
if(propertyName.indexOf("*")>=1) {
// barseries methods
lineSeries = (BarSeries) BarSeriesImpl.create();
} else {
lineSeries = (ScatterSeries) ScatterSeriesImpl.create();
}
*
*/
} // if lineSeries==null
lineSeries.setDataSet(orthoValues);
((LineSeries) lineSeries).getLineAttributes().setVisible(true);
((LineSeries) lineSeries).getMarkers().clear();
// Assign the line color
// based on selected property. Default is Blue
setColorDefs(seriesIndex);
// If this is the "selected" region of a graph set the marker type
// the series def
sdY = SeriesDefinitionImpl.create();
sdY.getSeriesPalette().update(-2);
sdY.getSeries().add(lineSeries);
yAxisPrimary.getSeriesDefinitions().add(sdY);
return;
}// addLineSeries
/**
* in response to user action temporarily remove the line series from the graph
*/
public void hide() {
lineSeries.setVisible(false);
visible = false;
}// hide
/**
* in response to user action add back the line series to the graph
*/
public void show() {
lineSeries.setVisible(true);
visible = true;
}// show
/**
* Overloaded and simple method to set the colors
* does not use the preferences
*
* Sets the colors for a n array of LineSeries given the property to Plot
* for each. Try to set color from the preferences (if specified for that
* property) otherwise sets line color to blue.
* @param propertyName
*
*/
public void setColorDefs(int index) {
// the default line color
if(index >= colorDefault.length) index = 0; // should never happen
ColorDefinition color = colorDefault[index];
this.lineSeries.setSeriesIdentifier(propertyName);
if (overlayMode) {
((LineSeries)this.lineSeries).getLineAttributes().setColor(color);
((LineSeries)this.lineSeries).getLineAttributes().setStyle(LineStyle.DOTTED_LITERAL);
} else {
((LineSeries)this.lineSeries).getLineAttributes().setColor(color);
}
}// getColorDefs
/**
* Sets the colors for a n array of LineSeries given the property to Plot
* for each. Try to set color from the preferences (if specified for that
* property) otherwise sets line color to blue.
* @param propertyName
*
*/
public void setColorDefs(String propertyName) {
// the default line color
// if possible get color from preferences
final Map<String, Color> colorMap = VisualizationPreferencePage.getColorMapping();
// default color
int colorIndex = seriesIndex % colorDefault.length;
ColorDefinition color = colorDefault[colorIndex];
// preferred color by name
String key = propertyName.substring(0,1);
if (colorMap.containsKey(key)) {
final Color c = colorMap.get(key);
color = ColorDefinitionImpl.create(c.getRed(), c.getGreen(), c.getBlue());
}
this.lineSeries.setSeriesIdentifier(propertyName);
if (overlayMode) {
((LineSeries)this.lineSeries).getLineAttributes().setColor(ColorDefinitionImpl.GREY());
((LineSeries)this.lineSeries).getLineAttributes().setStyle(LineStyle.DOTTED_LITERAL);
} else {
((LineSeries)this.lineSeries).getLineAttributes().setColor(color);
}
}// getColorDefs
/**
* length of the series
* @return number of data points
*/
public int getDataSize() {
return relativeValues.size();
}
// Accessors
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public List<Double> getRelativeValues() {
return relativeValues;
}
public void setRelativeValues(List<Double> relativeValues) {
this.relativeValues = relativeValues;
}
public void setLineSeries(LineSeries lineSeries) {
this.lineSeries = lineSeries;
}
}// DataSeries
////////////////////////////////////////////////////////
} // AggregateTimeSeriesCanvas