Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Archived » BIRT » Can't Refresh Chart rather than Re-Build and Render
Can't Refresh Chart rather than Re-Build and Render [message #538227] Sun, 06 June 2010 20:21 Go to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 123
Registered: July 2009
Senior Member
I have a chart rendered in an RCP View that will be refreshed very fast over a period of several seconds, and I want to minimize the flicker effect. I saw in some BIRT documentation found online that I could do a refresh rather than build and render on the Generator. But if I call refresh() on the Generator, I get a SWTException with the message "Graphic is disposed".

I've pasted my code below, adapted from an example I found online. It's a test case that plots a sine wave and changes the period of the wave every 500 msec. The code works, but there is some flicker with each update. If you un-comment the line in paintControl() that sets firstRender to false, it will attempt to refresh rather than build and render after the first paint operation. Then the SWTException I mentioned earlier will be thrown on gr.refresh(state). The exception is thrown in class Generator, when computing the chart; and I can't even find a sufficient guard to avoid calling refresh() when the Exception will be thrown.

public class SampleChartView extends ViewPart {

	public static final String ID = "net.midnightjava.charttest.views.SampleChartView";

	private static float p = 5;
	
	private static GeneratedChartState state;

	private static final class MyPaintListener implements PaintListener
	{

		boolean firstRender = true;

		public void paintControl(PaintEvent e)
		{
			IDeviceRenderer deviceRenderer = null;
			try {
				deviceRenderer = PluginSettings.instance().getDevice("dv.SWT");
			} catch (ChartException e1) {
				e1.printStackTrace();
			}
			deviceRenderer
			.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, e.gc);

			Rectangle rect = ((Composite) e.widget).getClientArea();
			Bounds bounds = BoundsImpl.create(rect.x + 2,
					rect.y + 2,
					rect.width - 4,
					rect.height - 4);
			bounds.scale(72d /
					deviceRenderer.getDisplayServer().getDpiResolution());

			Chart chart = null;
			if (firstRender) {
				chart = createSimpleLineChart(); 
			}

			Generator gr = Generator.instance();
			try
			{
				if (firstRender) {
					state  = gr.build(deviceRenderer.getDisplayServer(),
							chart,
							bounds,
							new RunTimeContext());

					gr.render(deviceRenderer, state);
				} else {
					gr.refresh(state);
				}
				//firstRender = false;
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
	}

	private Canvas canvas;

	public SampleChartView() {
		Job animator = new Job("Animator Job") {

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				if (p == 10) {
					p = 5;
				} else {
					p++;
				}
				if (!PlatformUI.getWorkbench().getDisplay().isDisposed()) {
					PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {

						@Override
						public void run() {
							if (canvas != null && !canvas.isDisposed()) {
								canvas.redraw();
							}
						}

					});
				}
				schedule(500);
				return Status.OK_STATUS;
			}

		};
		animator.setSystem(true);
		animator.schedule();
	}

	public void createPartControl(final Composite parent) {
		canvas = new Canvas(parent, SWT.NONE);
		canvas.addPaintListener(new MyPaintListener());
	}

	public static final Chart createSimpleLineChart()
	{
		ChartWithAxes cwaBar = ChartWithAxesImpl.create();
		cwaBar.getBlock().setBackground(ColorDefinitionImpl.BLACK());
		Plot plot = cwaBar.getPlot();
		plot.getOutline().setVisible(false);
		cwaBar.getTitle().getLabel().setVisible(false);

		Legend lg = cwaBar.getLegend();
		LineAttributes lia = lg.getOutline();
		lg.getText().getFont().setSize(16);
		lia.setStyle(LineStyle.SOLID_LITERAL);
		lg.getInsets().set(10, 5, 0, 0);
		lg.getOutline().setVisible(false);
		lg.setAnchor(Anchor.NORTH_LITERAL);
		lg.setVisible(false);

		AxisImpl xAxisPrimary = (AxisImpl) cwaBar.getPrimaryBaseAxes()[0];
		xAxisPrimary.setType(AxisType.LINEAR_LITERAL);
		xAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false);
		xAxisPrimary.getOrigin().setType(IntersectionType.MIN_LITERAL);
		xAxisPrimary.getTitle().setVisible(false);
		xAxisPrimary.getLabel().setVisible(false);
		xAxisPrimary.getLineAttributes().setVisible(false);

		AxisImpl yAxisPrimary = (AxisImpl) cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary);
		yAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false);
		yAxisPrimary.getTitle().setVisible(false);
		yAxisPrimary.setPercent(false);
		yAxisPrimary.getLabel().setVisible(false);
		yAxisPrimary.getLineAttributes().setVisible(false);

		Vector<Integer> vs = new Vector<Integer>();
		for (int i = 1; i <= 512; i++) {
			vs.add(i);
		}

		ArrayList<Double> vn1 = new ArrayList<Double>();
		for (float i = 1; i <= 512; i++) {
			vn1.add(40 * Math.sin(i / p) + 40);
		}

		NumberDataSet categoryValues = NumberDataSetImpl.create(vs);
		NumberDataSet orthoValues1 = NumberDataSetImpl.create(vn1);

		Series seCategory = SeriesImpl.create();
		seCategory.setDataSet(categoryValues);
		seCategory.setVisible(false);

		LineSeries ls = (LineSeries) LineSeriesImpl.create();
		ls.setDataSet(orthoValues1);
		ls.getLineAttributes().setColor(ColorDefinitionImpl.GREEN());
		ls.getMarkers().get(0).setVisible(false);

		SeriesDefinition sdX = SeriesDefinitionImpl.create();
		sdX.getSeriesPalette().shift(0);
		xAxisPrimary.getSeriesDefinitions().add(sdX);

		SeriesDefinition sdY = SeriesDefinitionImpl.create();
		sdY.getSeriesPalette().shift(0);
		yAxisPrimary.getSeriesDefinitions().add(sdY);

		sdX.getSeries().add(seCategory);
		sdY.getSeries().add(ls);

		return cwaBar;
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
		
	}
}
Re: Can't Refresh Chart rather than Re-Build and Render [message #538728 is a reply to message #538227] Tue, 08 June 2010 13:44 Go to previous messageGo to next message
Jason Weathersby is currently offline Jason WeathersbyFriend
Messages: 9167
Registered: July 2009
Senior Member

Mark,

Have you looked at the SWTChartViewer Example? You need to call build
every time. I am attaching the example.

Jason


/*********************************************************** ************
* Copyright (c) 2004, 2007 Actuate Corporation.
* 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:
* Actuate Corporation - initial API and implementation
************************************************************ ***********/

package org.eclipse.birt.chart.examples.api.viewer;

import org.eclipse.birt.chart.api.ChartEngine;
import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.examples.api.script.JavaScriptViewer;
import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.factory.GeneratedChartState;
import org.eclipse.birt.chart.factory.Generator;
import org.eclipse.birt.chart.log.ILogger;
import org.eclipse.birt.chart.log.Logger;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.ChartWithAxes;
import org.eclipse.birt.chart.model.attribute.AxisType;
import org.eclipse.birt.chart.model.attribute.Bounds;
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.Marker;
import org.eclipse.birt.chart.model.attribute.MarkerType;
import org.eclipse.birt.chart.model.attribute.Position;
import org.eclipse.birt.chart.model.attribute.RiserType;
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.ColorDefinitionI mpl;
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.TextDataSet;
import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl;
import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl;
import org.eclipse.birt.chart.model.data.impl.TextDataSetImpl;
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.BarSeries;
import org.eclipse.birt.chart.model.type.LineSeries;
import org.eclipse.birt.chart.model.type.impl.BarSeriesImpl;
import org.eclipse.birt.chart.model.type.impl.LineSeriesImpl;
import org.eclipse.birt.core.framework.PlatformConfig;
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.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SwtLiveChartViewer extends Composite implements PaintListener
{

private IDeviceRenderer idr = null;

private Chart cm = null;


private GeneratedChartState gcs = null;

private static SwtLiveChartViewer c3dViewer;

/**
* Used in building the chart for the first time
*/
private boolean bFirstPaint = true;

private static ILogger logger = Logger.getLogger(
JavaScriptViewer.class.getName( ) );

/**
* execute application
*
* @param args
*/
public static void main( String[] args )
{
Display display = Display.getDefault( );
Shell shell = new Shell( display, SWT.CLOSE );
shell.setSize( 600, 400 );
shell.setLayout( new GridLayout( ) );

c3dViewer = new SwtLiveChartViewer( shell, SWT.NO_BACKGROUND );
c3dViewer.setLayoutData( new GridData( GridData.FILL_BOTH ) );
c3dViewer.addPaintListener( c3dViewer );


shell.open( );
while ( !shell.isDisposed( ) )
{
if ( !display.readAndDispatch( ) )
display.sleep( );
}
display.dispose( );
}

/**
* Constructor
*/
SwtLiveChartViewer( Composite parent, int style )
{
super( parent, style );

try
{
PlatformConfig config = new PlatformConfig( );
config.setProperty( "STANDALONE", "true" ); //$NON-NLS-1$ //$NON-NLS-2$
idr = ChartEngine.instance( config ).getRenderer( "dv.SWT"
);//$NON-NLS-1$
}
catch ( ChartException pex )
{
logger.log( pex );
}

cm = createLiveChart( );

}

public static final Chart createLiveChart( )
{
ChartWithAxes cwaBar = ChartWithAxesImpl.create( );

// Plot
cwaBar.getBlock( ).setBackground( ColorDefinitionImpl.WHITE( ) );
Plot p = cwaBar.getPlot( );
p.getClientArea( ).setBackground( ColorDefinitionImpl.create( 255,
255,
225 ) );

// Legend
Legend lg = cwaBar.getLegend( );
LineAttributes lia = lg.getOutline( );
lg.getText( ).getFont( ).setSize( 16 );
lia.setStyle( LineStyle.SOLID_LITERAL );
lg.getInsets( ).setLeft( 10 );
lg.getInsets( ).setRight( 10 );

// Title
cwaBar.getTitle( )
.getLabel( )
.getCaption( )
.setValue( "Live Chart Demo" );//$NON-NLS-1$

// X-Axis
Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes( )[0];

xAxisPrimary.setType( AxisType.TEXT_LITERAL );
xAxisPrimary.getOrigin( ).setType( IntersectionType.VALUE_LITERAL );
xAxisPrimary.getOrigin( ).setType( IntersectionType.MIN_LITERAL );

xAxisPrimary.getTitle( )
.getCaption( )
.setValue( "Category Text X-Axis" );//$NON-NLS-1$
xAxisPrimary.setTitlePosition( Position.BELOW_LITERAL );

xAxisPrimary.getLabel( ).getCaption( ).getFont( ).setRotation( 75 );
xAxisPrimary.setLabelPosition( Position.BELOW_LITERAL );

xAxisPrimary.getMajorGrid( ).setTickStyle( TickStyle.BELOW_LITERAL );
xAxisPrimary.getMajorGrid( )
.getLineAttributes( )
.setStyle( LineStyle.DOTTED_LITERAL );
xAxisPrimary.getMajorGrid( )
.getLineAttributes( )
.setColor( ColorDefinitionImpl.create( 64, 64, 64 ) );
xAxisPrimary.getMajorGrid( ).getLineAttributes( ).setVisible( true );

// Y-Axis
Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis( xAxisPrimary );

yAxisPrimary.getLabel( ).getCaption( ).setValue( "Price Axis"
);//$NON-NLS-1$
yAxisPrimary.getLabel( ).getCaption( ).getFont( ).setRotation( 37 );
yAxisPrimary.setLabelPosition( Position.LEFT_LITERAL );

yAxisPrimary.setTitlePosition( Position.LEFT_LITERAL );
yAxisPrimary.getTitle( ).getCaption( ).setValue( "Linear Value Y-Axis"
);//$NON-NLS-1$

yAxisPrimary.setType( AxisType.LINEAR_LITERAL );

yAxisPrimary.getMajorGrid( ).setTickStyle( TickStyle.LEFT_LITERAL );
yAxisPrimary.getMajorGrid( )
.getLineAttributes( )
.setStyle( LineStyle.DOTTED_LITERAL );
yAxisPrimary.getMajorGrid( )
.getLineAttributes( )
.setColor( ColorDefinitionImpl.RED( ) );
yAxisPrimary.getMajorGrid( ).getLineAttributes( ).setVisible( true );

// X-Series
Series seCategory = SeriesImpl.create( );
SeriesDefinition sdX = SeriesDefinitionImpl.create( );
xAxisPrimary.getSeriesDefinitions( ).add( sdX );
sdX.getSeries( ).add( seCategory );

// Y-Series (1)
BarSeries bs1 = (BarSeries) BarSeriesImpl.create( );
bs1.setSeriesIdentifier( "Unit Price" );//$NON-NLS-1$
bs1.setRiserOutline( null );
bs1.setRiser( RiserType.RECTANGLE_LITERAL );

// Y-Series (2)
LineSeries ls1 = (LineSeries) LineSeriesImpl.create( );
ls1.setSeriesIdentifier( "Quantity" );//$NON-NLS-1$
ls1.getLineAttributes( ).setColor( ColorDefinitionImpl.GREEN( ) );
for ( int i = 0; i < ls1.getMarkers( ).size( ); i++ )
{
( (Marker) ls1.getMarkers( ).get( i ) ).setType(
MarkerType.BOX_LITERAL );
}
ls1.setCurve( true );

SeriesDefinition sdY = SeriesDefinitionImpl.create( );
yAxisPrimary.getSeriesDefinitions( ).add( sdY );
sdY.getSeriesPalette( ).shift( -1 );
sdY.getSeries( ).add( bs1 );
sdY.getSeries( ).add( ls1 );

// Update data
updateDataSet( cwaBar );
return cwaBar;
}

static final void updateDataSet( ChartWithAxes cwaBar )
{
// Associate with Data Set
TextDataSet categoryValues = TextDataSetImpl.create( sa );
NumberDataSet seriesOneValues = NumberDataSetImpl.create( da1 );
NumberDataSet seriesTwoValues = NumberDataSetImpl.create( da2 );

// X-Axis
Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes( )[0];
SeriesDefinition sdX = (SeriesDefinition)
xAxisPrimary.getSeriesDefinitions( )
.get( 0 );
( (Series) sdX.getSeries( ).get( 0 ) ).setDataSet( categoryValues );

// Y-Axis
Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis( xAxisPrimary );
SeriesDefinition sdY = (SeriesDefinition)
yAxisPrimary.getSeriesDefinitions( )
.get( 0 );
( (Series) sdY.getSeries( ).get( 0 ) ).setDataSet( seriesOneValues );
( (Series) sdY.getSeries( ).get( 1 ) ).setDataSet( seriesTwoValues );
}
// Live Date Set
private static final String[] sa = {
"One", "Two", "Three", "Four",
"Five" ,//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON- NLS-5$
"Six", "Seven", "Eight", "Nine",
"Ten" };//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON -NLS-5$
private static final double[] da1 = {
56.99,
352.95,
-201.95,
299.95,
-95.95,
25.45,
129.33,
-26.5,
43.5,
122
};

private static final double[] da2 = {
20, 35, 59, 105, 150, -37, -65, -99, -145, -185
};

private Image imgChart;

private GC gcImage;

private Bounds bo;

static final void scrollData( ChartWithAxes cwa )
{
// Scroll the bar (Y) series
double dTemp = da1[0];
for ( int i = 0; i < da1.length - 1; i++ )
{
da1[i] = da1[i + 1];
}
da1[da1.length - 1] = dTemp;

// Scroll the line (Y) series
dTemp = da2[0];
for ( int i = 0; i < da2.length - 1; i++ )
{
da2[i] = da2[i + 1];
}
da2[da2.length - 1] = dTemp;

// Scroll X series
String sTemp = sa[0];
for ( int i = 0; i < sa.length - 1; i++ )
{
sa[i] = sa[i + 1];
}
sa[sa.length - 1] = sTemp;

updateDataSet( cwa );
}

/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.PaintListener#paintControl(org.eclips e.swt.events
* .PaintEvent)
*/
public final void paintControl( PaintEvent e )
{
Rectangle d = this.getClientArea( );
if ( bFirstPaint )
{
imgChart = new Image( this.getDisplay( ), d );
gcImage = new GC( imgChart );
idr.setProperty( IDeviceRenderer.GRAPHICS_CONTEXT, gcImage );

bo = BoundsImpl.create( 0, 0, d.width, d.height );
bo.scale( 72d / idr.getDisplayServer( ).getDpiResolution( ) );
}

Generator gr = Generator.instance( );

try
{
gcs = gr.build( idr.getDisplayServer( ), cm, bo, null, null, null );
gr.render( idr, gcs );
GC gc = e.gc;
gc.drawImage( imgChart, d.x, d.y );
}
catch ( ChartException ce )
{
ce.printStackTrace( );
}

bFirstPaint = false;

Display.getDefault( ).timerExec( 100, new Runnable( ) {

public void run( )
{
chartRefresh( );
}
} );

}

/*
* (non-Javadoc)
*
* @see
*
org.eclipse.swt.events.SelectionListener#widgetDefaultSelect ed(org.eclipse
* .swt.events.SelectionEvent)
*/
private void chartRefresh( )
{
if ( !isDisposed( ) )
{
final Generator gr = Generator.instance( );
scrollData( (ChartWithAxes) cm );

// Refresh
try
{
gr.refresh( gcs );
}
catch ( ChartException ex )
{
ex.printStackTrace( );
}
redraw( );
}

}

}


On 6/6/2010 4:21 PM, Mark Leone wrote:
> I have a chart rendered in an RCP View that will be refreshed very fast
> over a period of several seconds, and I want to minimize the flicker
> effect. I saw in some BIRT documentation found online that I could do a
> refresh rather than build and render on the Generator. But if I call
> refresh() on the Generator, I get a SWTException with the message
> "Graphic is disposed".
>
> I've pasted my code below, adapted from an example I found online. It's
> a test case that plots a sine wave and changes the period of the wave
> every 500 msec. The code works, but there is some flicker with each
> update. If you un-comment the line in paintControl() that sets
> firstRender to false, it will attempt to refresh rather than build and
> render after the first paint operation. Then the SWTException I
> mentioned earlier will be thrown on gr.refresh(state). The exception is
> thrown in class Generator, when computing the chart; and I can't even
> find a sufficient guard to avoid calling refresh() when the Exception
> will be thrown.
>
> public class SampleChartView extends ViewPart {
>
> public static final String ID =
> "net.midnightjava.charttest.views.SampleChartView";
>
> private static float p = 5;
>
> private static GeneratedChartState state;
>
> private static final class MyPaintListener implements PaintListener
> {
>
> boolean firstRender = true;
>
> public void paintControl(PaintEvent e)
> {
> IDeviceRenderer deviceRenderer = null;
> try {
> deviceRenderer = PluginSettings.instance().getDevice("dv.SWT");
> } catch (ChartException e1) {
> e1.printStackTrace();
> }
> deviceRenderer
> .setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, e.gc);
>
> Rectangle rect = ((Composite) e.widget).getClientArea();
> Bounds bounds = BoundsImpl.create(rect.x + 2,
> rect.y + 2,
> rect.width - 4,
> rect.height - 4);
> bounds.scale(72d /
> deviceRenderer.getDisplayServer().getDpiResolution());
>
> Chart chart = null;
> if (firstRender) {
> chart = createSimpleLineChart(); }
>
> Generator gr = Generator.instance();
> try
> {
> if (firstRender) {
> state = gr.build(deviceRenderer.getDisplayServer(),
> chart,
> bounds,
> new RunTimeContext());
>
> gr.render(deviceRenderer, state);
> } else {
> gr.refresh(state);
> }
> //firstRender = false;
> }
> catch (Exception ex)
> {
> ex.printStackTrace();
> }
> }
> }
>
> private Canvas canvas;
>
> public SampleChartView() {
> Job animator = new Job("Animator Job") {
>
> @Override
> protected IStatus run(IProgressMonitor monitor) {
> if (p == 10) {
> p = 5;
> } else {
> p++;
> }
> if (!PlatformUI.getWorkbench().getDisplay().isDisposed()) {
> PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
>
> @Override
> public void run() {
> if (canvas != null && !canvas.isDisposed()) {
> canvas.redraw();
> }
> }
>
> });
> }
> schedule(500);
> return Status.OK_STATUS;
> }
>
> };
> animator.setSystem(true);
> animator.schedule();
> }
>
> public void createPartControl(final Composite parent) {
> canvas = new Canvas(parent, SWT.NONE);
> canvas.addPaintListener(new MyPaintListener());
> }
>
> public static final Chart createSimpleLineChart()
> {
> ChartWithAxes cwaBar = ChartWithAxesImpl.create();
> cwaBar.getBlock().setBackground(ColorDefinitionImpl.BLACK()) ;
> Plot plot = cwaBar.getPlot();
> plot.getOutline().setVisible(false);
> cwaBar.getTitle().getLabel().setVisible(false);
>
> Legend lg = cwaBar.getLegend();
> LineAttributes lia = lg.getOutline();
> lg.getText().getFont().setSize(16);
> lia.setStyle(LineStyle.SOLID_LITERAL);
> lg.getInsets().set(10, 5, 0, 0);
> lg.getOutline().setVisible(false);
> lg.setAnchor(Anchor.NORTH_LITERAL);
> lg.setVisible(false);
>
> AxisImpl xAxisPrimary = (AxisImpl) cwaBar.getPrimaryBaseAxes()[0];
> xAxisPrimary.setType(AxisType.LINEAR_LITERAL);
> xAxisPrimary.getMajorGrid().getTickAttributes().setVisible(f alse);
> xAxisPrimary.getOrigin().setType(IntersectionType.MIN_LITERA L);
> xAxisPrimary.getTitle().setVisible(false);
> xAxisPrimary.getLabel().setVisible(false);
> xAxisPrimary.getLineAttributes().setVisible(false);
>
> AxisImpl yAxisPrimary = (AxisImpl)
> cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary);
> yAxisPrimary.getMajorGrid().getTickAttributes().setVisible(f alse);
> yAxisPrimary.getTitle().setVisible(false);
> yAxisPrimary.setPercent(false);
> yAxisPrimary.getLabel().setVisible(false);
> yAxisPrimary.getLineAttributes().setVisible(false);
>
> Vector<Integer> vs = new Vector<Integer>();
> for (int i = 1; i <= 512; i++) {
> vs.add(i);
> }
>
> ArrayList<Double> vn1 = new ArrayList<Double>();
> for (float i = 1; i <= 512; i++) {
> vn1.add(40 * Math.sin(i / p) + 40);
> }
>
> NumberDataSet categoryValues = NumberDataSetImpl.create(vs);
> NumberDataSet orthoValues1 = NumberDataSetImpl.create(vn1);
>
> Series seCategory = SeriesImpl.create();
> seCategory.setDataSet(categoryValues);
> seCategory.setVisible(false);
>
> LineSeries ls = (LineSeries) LineSeriesImpl.create();
> ls.setDataSet(orthoValues1);
> ls.getLineAttributes().setColor(ColorDefinitionImpl.GREEN()) ;
> ls.getMarkers().get(0).setVisible(false);
>
> SeriesDefinition sdX = SeriesDefinitionImpl.create();
> sdX.getSeriesPalette().shift(0);
> xAxisPrimary.getSeriesDefinitions().add(sdX);
>
> SeriesDefinition sdY = SeriesDefinitionImpl.create();
> sdY.getSeriesPalette().shift(0);
> yAxisPrimary.getSeriesDefinitions().add(sdY);
>
> sdX.getSeries().add(seCategory);
> sdY.getSeries().add(ls);
>
> return cwaBar;
> }
>
> @Override
> public void setFocus() {
> // TODO Auto-generated method stub
>
> }
> }
Re: Can't Refresh Chart rather than Re-Build and Render [message #543906 is a reply to message #538728] Thu, 01 July 2010 04:20 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 123
Registered: July 2009
Senior Member
Jason,

I'm just now able to get back to this problem. Thanks for posting the code. I tried it and found that it has the same deficiency of the example code I posted, which is that calling redraw() in the PaintListener produces a pronounced flicker. At the update rate used in the example, the chart is unreadable.

I found a way to update the chart directly with a backgrouond job, apart from the PaintListener. This works well with respect to the flicker problem, but since I'm not using a PaintListener, the chart doesn't adjust its size when the window is re-sized. I tried various permutations of code in PaintListener.paintControl(), using the code you posted for ideas, but everything I tried throws some version of org.eclipse.birt.YouDontKnowWhatYoureDoingException.

Can anyone tell me how to avoid the flicker in the code Jason posted? Or can someone tell me how to implement paintControl() in my example below to handle re-sizing of the parent Composite?

My code runs in an RCP app, so what I've posted is an instance of IViewPart that draws a sample chart in the view. It's a modulated sine wave, with the frequency of the modulated signal cycling through a range of discrete values. I'm not sure how to translate this to a standalone SWT application, as I can't figure out how to resolve the birt dependencies other than within the OSGI runtime. I ran the code Jason posted in an RCP view, and saw the flickering I mentioned. Perhaps that doesn't occur when run as a standalone SWT app.

import java.util.ArrayList;
import java.util.Vector;

import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.factory.GeneratedChartState;
import org.eclipse.birt.chart.factory.Generator;
import org.eclipse.birt.chart.factory.RunTimeContext;
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.IntersectionType;
import org.eclipse.birt.chart.model.attribute.LineAttributes;
import org.eclipse.birt.chart.model.attribute.LineStyle;
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.Series;
import org.eclipse.birt.chart.model.component.impl.AxisImpl;
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.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.LineSeriesImpl;
import org.eclipse.birt.chart.util.PluginSettings;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
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.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

public class SampleSinePlotView extends ViewPart implements PaintListener {

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "net.midnightjava.charttest.views.SampleSinePlotView";

	private static final long REDRAW_PERIOD = 100;

	private static float p = 10f;

	private Canvas canvas;

	private Job startPlotJob = new Job("Start Plot Job") {

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			if (canvas != null) {
				PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {

					public void run() {
						startPlotting();
					}

				});
			} else {
				schedule(50);
			}
			return Status.OK_STATUS;
		}

	};

	private IDeviceRenderer deviceRenderer;

	private Bounds bounds;

	protected Chart chart;

	public SampleSinePlotView() {
	}

	public void createPartControl(final Composite parent) {
		GridLayoutFactory glf = GridLayoutFactory.fillDefaults();
		glf.applyTo(parent);
		canvas = new Canvas(parent, SWT.NONE);
		canvas.addPaintListener(this);
		GridDataFactory gdf = GridDataFactory.fillDefaults();
		gdf.grab(true, true).applyTo(canvas);
		startPlotJob.setSystem(true);
		startPlotJob.schedule();
	}

	private void startPlotting() {
		final Generator gr = Generator.instance();
		try {
			deviceRenderer = PluginSettings.instance().getDevice("dv.SWT");
			deviceRenderer.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, new GC(canvas));

			Rectangle rect = canvas.getClientArea();
			bounds = BoundsImpl.create(rect.x + 2,
					rect.y + 2,
					rect.width - 4,
					rect.height - 4);
			bounds.scale(72d /
					deviceRenderer.getDisplayServer().getDpiResolution());
			final Job plotJob = new Job("Plot Job") {

				private GeneratedChartState state;
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					scrollData();
					chart = createSimpleLineChart(); 
					try
					{
						if (!PlatformUI.getWorkbench().getDisplay().isDisposed()) {
							state = gr.build(deviceRenderer.getDisplayServer(),
									chart,
									bounds,
									new RunTimeContext());
							gr.render(deviceRenderer, state);
						}
					}
					catch (Exception ex)
					{
						ex.printStackTrace();
					}
					schedule(REDRAW_PERIOD);
					return Status.OK_STATUS;
				}

			};
			plotJob.setSystem(true);
			plotJob.schedule();
		} catch (ChartException e1) {
			e1.printStackTrace();
		}


	}

	protected void scrollData() {
		if (p >= 20f) {
			p = 10f;
		} else {
			p++;
		}
	}

	public static final Chart createSimpleLineChart()
	{
		ChartWithAxes cwaBar = ChartWithAxesImpl.create();
		cwaBar.getBlock().setBackground(ColorDefinitionImpl.BLACK());
		Plot plot = cwaBar.getPlot();
		plot.getOutline().setVisible(false);
		cwaBar.getTitle().getLabel().setVisible(false);

		Legend lg = cwaBar.getLegend();
		LineAttributes lia = lg.getOutline();
		lg.getText().getFont().setSize(16);
		lia.setStyle(LineStyle.SOLID_LITERAL);
		lg.getInsets().set(10, 5, 0, 0);
		lg.getOutline().setVisible(false);
		lg.setAnchor(Anchor.NORTH_LITERAL);
		lg.setVisible(false);

		AxisImpl xAxisPrimary = (AxisImpl) cwaBar.getPrimaryBaseAxes()[0];
		xAxisPrimary.setType(AxisType.LINEAR_LITERAL);
		xAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false);
		xAxisPrimary.getOrigin().setType(IntersectionType.MIN_LITERAL);
		xAxisPrimary.getTitle().setVisible(false);
		xAxisPrimary.getLabel().setVisible(false);
		xAxisPrimary.getLineAttributes().setVisible(false);

		AxisImpl yAxisPrimary = (AxisImpl) cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary);
		yAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false);
		yAxisPrimary.getTitle().setVisible(false);
		yAxisPrimary.setPercent(false);
		yAxisPrimary.getLabel().setVisible(false);
		yAxisPrimary.getLineAttributes().setVisible(false);

		Vector<Integer> vs = new Vector<Integer>();
		for (int i = 1; i <= 512; i++) {
			vs.add(i);
		}

		ArrayList<Double> vn1 = new ArrayList<Double>();
		for (float i = 1; i <= 512; i++) {
			vn1.add(40 * Math.sin(i / 0.1) + 40 + 40 * Math.sin(i / p) + 40);
		}

		NumberDataSet categoryValues = NumberDataSetImpl.create(vs);
		NumberDataSet orthoValues1 = NumberDataSetImpl.create(vn1);

		Series seCategory = SeriesImpl.create();
		seCategory.setDataSet(categoryValues);
		seCategory.setVisible(false);

		LineSeries ls = (LineSeries) LineSeriesImpl.create();
		ls.setDataSet(orthoValues1);
		ls.getLineAttributes().setColor(ColorDefinitionImpl.GREEN());
		ls.getMarkers().get(0).setVisible(false);

		SeriesDefinition sdX = SeriesDefinitionImpl.create();
		sdX.getSeriesPalette().shift(0);
		xAxisPrimary.getSeriesDefinitions().add(sdX);

		SeriesDefinition sdY = SeriesDefinitionImpl.create();
		sdY.getSeriesPalette().shift(0);
		yAxisPrimary.getSeriesDefinitions().add(sdY);

		sdX.getSeries().add(seCategory);
		sdY.getSeries().add(ls);

		return cwaBar;
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub

	}

	public void paintControl(PaintEvent e) {
		//??
	}
}
Re: Can't Refresh Chart rather than Re-Build and Render [message #543907 is a reply to message #543906] Thu, 01 July 2010 04:26 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 123
Registered: July 2009
Senior Member
After posting, I thought of a way to run the code Jason provided as a standalone SWT app. I just create a separate Shell in createPartControl() and pass it to the SwtLiveChartViewer constructor, which then runs in a Shell outside the RCP runtime workbench.

When I did it this way, the flicker did not occur. Then I discovered that I was missing the SWT.NO_BACKGROUND style setting in the SwtLiveChartViewer constructor for the RCP app version. When I use that, the flicker does not occur, even when run in the RCP app.

However, I'm still not any better off than with the code I came up with, as this implementation does not handle re-sizing of the window either. In fact, it's worse than with my code, because instead of just re-drawing the plot at the same size in a larger window, it re-draws it elsewhere and leaves parts of the original plot behind, garbling the image. This happens in the RCP app and also as a stand-alone SWT app (tested by adding SWT.RESIZE as a style bit to the Shell constructor).

So the question remains, how can I handle window re-sizing for a dynamically updating chart?

[Updated on: Thu, 01 July 2010 04:45]

Report message to a moderator

Re: Can't Refresh Chart rather than Re-Build and Render [message #544075 is a reply to message #543907] Thu, 01 July 2010 13:58 Go to previous messageGo to next message
Jason Weathersby is currently offline Jason WeathersbyFriend
Messages: 9167
Registered: July 2009
Senior Member

Mark,

Can you open a bug entry for this?

Jason

On 7/1/2010 12:26 AM, Mark Leone wrote:
> After posting, I thought of a way to run the code Jason provided as a
> standalone SWT app. I just create a separate Shell in
> createPartControl() and pass it to the SwtLiveChartViewer constructor,
> whch then runs in a Shell outside the RCP runtime workbench.
>
> When I do it that way, the flicker does not occur. So it's an artifact
> of running this code within an RCP app.
Re: Can't Refresh Chart rather than Re-Build and Render [message #544124 is a reply to message #544075] Thu, 01 July 2010 16:35 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 123
Registered: July 2009
Senior Member
Jason,

I edited my last response shortly after posting, and you seem to have responded to the earlier version (per the text you quoted). So to be clear, there's no issue with flicker when running as an RCP app. My only remaining question is how to handle window re-sizing. The example code was written with a shell that can't be re-sized, so I'm wondering if the behavior I observed is a known issue or a feature.

So with this clarification, do you still think a bug is in order for the re-size behavior?

Re: Can't Refresh Chart rather than Re-Build and Render [message #544131 is a reply to message #544124] Thu, 01 July 2010 16:46 Go to previous messageGo to next message
Jason Weathersby is currently offline Jason WeathersbyFriend
Messages: 9167
Registered: July 2009
Senior Member

Mark,

Can you download these examples:
http://www.birt-exchange.org/org/devshare/deploying-birt-rep orts/1187-eclipsecon-2010-birt-metal-ppt/

In the workspace there is a project called
org.eclipse.birt.examples.rcpchartengine which updates a chart and
renders it in an rcp app with re-sizable window. When I resize I do not
get any flicker but can you give it a try?

Jason

On 7/1/2010 12:35 PM, Mark Leone wrote:
> Jason,
>
> I edited my last response shortly after posting, and you seem to have
> responded to the earlier version (per the text you quoted). So to be
> clear, there's no issue with flicker when running as an RCP app. My only
> remaining question is how to handle window re-sizing. The example code
> was written with a shell that can't be re-sized, so I'm wondering if the
> behavior I observed is a known issue or a feature.
>
> So with this clarification, do you still think a bug is in order for the
> re-size behavior?
>
>
Re: Can't Refresh Chart rather than Re-Build and Render [message #544429 is a reply to message #544131] Fri, 02 July 2010 16:00 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 123
Registered: July 2009
Senior Member
Thanks, Jason. I see now how the control listener is used to handle re-sizing behavior. The example worked fine for me, including re-sizing and detaching the view.

Can you clarify what the update notifier does? I tried running without that property set on the display renderer, and I didn't see any different behavior.
Re: Can't Refresh Chart rather than Re-Build and Render [message #544447 is a reply to message #544429] Fri, 02 July 2010 16:45 Go to previous message
Jason Weathersby is currently offline Jason WeathersbyFriend
Messages: 9167
Registered: July 2009
Senior Member

Mark,

It is used for event handling when you have triggers on the chart. For
example with images that produce maps:
gcs = gr.build(
dServer,
cm,
bo,
null,
null,
null );
dRenderer.setProperty(IDeviceRenderer.UPDATE_NOTIFIER, new
EmptyUpdateNotifier( cm, gcs.getChartModel()));

gr.render( dRenderer, gcs );
String im = ((IImageMapEmitter)dRenderer).getImageMap();

BufferedWriter out = new BufferedWriter( new FileWriter(OUTPUT_HTML));

out.write("<html>");
out.newLine();
out.write("<body>");
out.newLine();
out.write("<div>");
out.newLine();
out.write("<map name='testmap'>");
out.write(im);
out.write("</map>");
out.newLine();
out.write( "<img id=myimage src='standalone.png'
usemap='#testmap'></img>");
out.newLine();
out.write("</div>");
out.newLine();
out.write("</body>");
out.newLine();
out.write("</html>");
out.newLine();
out.close();

If you comment out the update notifier the Image Map will not be created.

Jason

On 7/2/2010 12:00 PM, Mark Leone wrote:
> Thanks, Jason. I see now how the control listener is used to handle
> re-sizing behavior. The example worked fine for me, including re-sizing
> and detaching the view.
>
> Can you clarify what the update notifier does? I tried running without
> that property set on the display renderer, and I didn't see any
> different behavior.
Previous Topic:BIRT report on iServer Express
Next Topic:Fetching report parameter value
Goto Forum:
  


Current Time: Fri Apr 19 23:33:39 GMT 2024

Powered by FUDForum. Page generated in 0.04161 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top