/******************************************************************************* * Copyright (c) 2008-2011 SWTChart project. All rights reserved. * * This code is distributed under the terms of the Eclipse Public License v1.0 * which is available at http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.swtchart.internal; import java.util.ArrayList; import java.util.List; 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.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.swtchart.Chart; import org.swtchart.IAxis; import org.swtchart.IBarSeries; import org.swtchart.ICustomPaintListener; import org.swtchart.ILineSeries; import org.swtchart.IPlotArea; import org.swtchart.ISeries; import org.swtchart.ISeriesSet; import org.swtchart.internal.series.Series; import org.swtchart.internal.series.SeriesSet; /** * Plot area to draw series and grids. */ public class PlotArea extends Composite implements PaintListener, IPlotArea { /** the chart */ protected Chart chart; /** the set of plots */ protected SeriesSet seriesSet; /** the image cache */ private Image imageCache; /** the state indicating if image cache has to be updated */ private boolean updateImageCache; /** the custom paint listeners */ List<ICustomPaintListener> paintListeners; /** the default background color */ private static final int DEFAULT_BACKGROUND = SWT.COLOR_WHITE; /** * Constructor. * * @param chart * the chart * @param style * the style */ public PlotArea(Chart chart, int style) { super(chart, style | SWT.NO_BACKGROUND); this.chart = chart; seriesSet = new SeriesSet(chart); updateImageCache = true; paintListeners = new ArrayList<ICustomPaintListener>(); setBackground(Display.getDefault().getSystemColor(DEFAULT_BACKGROUND)); addPaintListener(this); } /** * Gets the set of series. * * @return the set of series */ public ISeriesSet getSeriesSet() { return seriesSet; } /* * @see Control#setBounds(int, int, int, int) */ @Override public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); ((SeriesSet) getSeriesSet()).compressAllSeries(); } /* * @see Control#setBackground(Color) */ @Override public void setBackground(Color color) { if (color == null) { super.setBackground(Display.getDefault().getSystemColor( DEFAULT_BACKGROUND)); } else { super.setBackground(color); } } /* * @see IPlotArea#addCustomPaintListener(ICustomPaintListener) */ public void addCustomPaintListener(ICustomPaintListener listener) { paintListeners.add(listener); } /* * @see IPlotArea#removeCustomPaintListener(ICustomPaintListener) */ public void removeCustomPaintListener(ICustomPaintListener listener) { paintListeners.remove(listener); } /* * @see PaintListener#paintControl(PaintEvent) */ public void paintControl(PaintEvent e) { if (updateImageCache) { Point p = getSize(); if (imageCache != null && !imageCache.isDisposed()) { imageCache.dispose(); } imageCache = new Image(Display.getCurrent(), p.x, p.y); GC gc = new GC(imageCache); // draw the plot area background gc.setBackground(getBackground()); gc.fillRectangle(0, 0, p.x, p.y); // draw grid for (IAxis axis : chart.getAxisSet().getAxes()) { ((Grid) axis.getGrid()).draw(gc, p.x, p.y); } // draw behind series GC prevGC = e.gc; e.gc = gc; for (ICustomPaintListener listener : paintListeners) { if (listener.drawBehindSeries()) { listener.paintControl(e); } } // draw series. The line series should be drawn on bar series. for (ISeries series : chart.getSeriesSet().getSeries()) { if (series instanceof IBarSeries) { ((Series) series).draw(gc, p.x, p.y); } } for (ISeries series : chart.getSeriesSet().getSeries()) { if (series instanceof ILineSeries) { ((Series) series).draw(gc, p.x, p.y); } } // draw over series for (ICustomPaintListener listener : paintListeners) { if (!listener.drawBehindSeries()) { listener.paintControl(e); } } e.gc = prevGC; gc.dispose(); updateImageCache = false; } e.gc.drawImage(imageCache, 0, 0); } /* * @see Control#update() */ @Override public void update() { super.update(); updateImageCache = true; } /* * @see Control#redraw() */ @Override public void redraw() { super.redraw(); updateImageCache = true; } /* * @see Widget#dispose() */ @Override public void dispose() { super.dispose(); seriesSet.dispose(); if (imageCache != null && !imageCache.isDisposed()) { imageCache.dispose(); } } }