| 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.adapters.color.STEMColor; |
| 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.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, STEMColor> 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 STEMColor c = colorMap.get(key); |
| color = ColorDefinitionImpl.create((int)(c.getRed() * 255.0), (int)(c.getGreen() * 255.0), (int)(c.getBlue() * 255.0)); |
| } |
| 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).getLineAttributes().setThickness(3); |
| ((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, STEMColor> 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 STEMColor c = colorMap.get(key); |
| color = ColorDefinitionImpl.create((int)(c.getRed() * 255.0), (int)(c.getGreen() * 255.0), (int)(c.getBlue() * 255.0)); |
| } |
| |
| 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 |