Project: Birt
Bug 274779 Associated Y axis issue with SWT renderer
Reported: 2009-05-04 02:02:49 | Status: verified fixed

Build ID: M20080911-1700 Steps To Reproduce: 1. Take a ChartWithAxes, 2 Y axes, X axis with NumberDataSet 2. Render chat using a SWT renderer 3. Toggle X axis type from TEXT to LINEAR to LOGARITHMIC 4. When application is running, see at the distances between the left Y axis and X axis, right Y axis and X axis. You will see that the distance between the right Y axis and the X axis is larger than the distance between the left Y axis and the X axis. More information: Test code (based on MultipleYAxes example) ========================================== package demo2; import org.eclipse.birt.chart.api.ChartEngine; 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.IGenerator; 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.Marker; import org.eclipse.birt.chart.model.attribute.MarkerType; 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.AxisImpl; import org.eclipse.birt.chart.model.component.impl.SeriesImpl; import org.eclipse.birt.chart.model.data.BaseSampleData; import org.eclipse.birt.chart.model.data.DataFactory; import org.eclipse.birt.chart.model.data.NumberDataSet; import org.eclipse.birt.chart.model.data.OrthogonalSampleData; import org.eclipse.birt.chart.model.data.SampleData; 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.type.LineSeries; import org.eclipse.birt.chart.model.type.impl.LineSeriesImpl; import org.eclipse.birt.core.framework.PlatformConfig; import org.eclipse.core.runtime.Assert; 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.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class MultipleYAxes { public static final Chart createMultipleYAxes() { ChartWithAxes cwaBar = ChartWithAxesImpl.create(); cwaBar.setType("Line Chart"); //$NON-NLS-1$ cwaBar.setSubType("Overlay"); //$NON-NLS-1$ // Plot cwaBar.getBlock().setBackground(ColorDefinitionImpl.WHITE()); cwaBar.getPlot().getClientArea().setBackground(ColorDefinitionImpl.create(255, 255, 225)); // Title cwaBar.getTitle().getLabel().getCaption().setValue("Line Chart with Multiple Y Axis");//$NON-NLS-1$ // Legend 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); // X-Axis Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes()[0]; /* * Y axis 2 offset issue: toggle axis type here */ //xAxisPrimary.setType( AxisType.TEXT_LITERAL ); //xAxisPrimary.setType( AxisType.LINEAR_LITERAL); xAxisPrimary.setType(AxisType.LOGARITHMIC_LITERAL); xAxisPrimary.getScale().setMax(NumberDataElementImpl.create(6.0)); xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.BELOW_LITERAL); xAxisPrimary.getOrigin().setType(IntersectionType.MIN_LITERAL); // Y-Axis Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary); yAxisPrimary.getMajorGrid().setTickStyle(TickStyle.LEFT_LITERAL); yAxisPrimary.getScale().setStep(5.0); // Y-Axis (2) Axis yAxis = AxisImpl.create(Axis.ORTHOGONAL); yAxis.setType(AxisType.LINEAR_LITERAL); yAxis.getMajorGrid().setTickStyle(TickStyle.RIGHT_LITERAL); yAxis.setLabelPosition(Position.RIGHT_LITERAL); yAxis.getScale().setStep(5.0); xAxisPrimary.getAssociatedAxes().add(yAxis); // Data Set // TextDataSet categoryValues = TextDataSetImpl.create( new String[]{ // "March", "April", "May", "June", "July"} );//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$ NumberDataSet categoryValues = NumberDataSetImpl.create(new double[] { 1, 2, 3, 4, 5 }); NumberDataSet orthoValues1 = NumberDataSetImpl.create(new double[] { 12.5, 19.6, 18.3, 13.2, 26.5 }); NumberDataSet orthoValues2 = NumberDataSetImpl.create(new double[] { 22.7, 23.6, 38.3, 43.2, 40.5 }); SampleData sd = DataFactory.eINSTANCE.createSampleData(); BaseSampleData sdBase = DataFactory.eINSTANCE.createBaseSampleData(); sdBase.setDataSetRepresentation("");//$NON-NLS-1$ sd.getBaseSampleData().add(sdBase); OrthogonalSampleData sdOrthogonal1 = DataFactory.eINSTANCE.createOrthogonalSampleData(); sdOrthogonal1.setDataSetRepresentation("");//$NON-NLS-1$ sdOrthogonal1.setSeriesDefinitionIndex(0); sd.getOrthogonalSampleData().add(sdOrthogonal1); OrthogonalSampleData sdOrthogonal2 = DataFactory.eINSTANCE.createOrthogonalSampleData(); sdOrthogonal2.setDataSetRepresentation("");//$NON-NLS-1$ sdOrthogonal2.setSeriesDefinitionIndex(1); sd.getOrthogonalSampleData().add(sdOrthogonal2); cwaBar.setSampleData(sd); // X-Series Series seCategory = SeriesImpl.create(); seCategory.setDataSet(categoryValues); SeriesDefinition sdX = SeriesDefinitionImpl.create(); xAxisPrimary.getSeriesDefinitions().add(sdX); sdX.getSeries().add(seCategory); // Y-Series (1) LineSeries ls1 = (LineSeries) LineSeriesImpl.create(); ls1.setSeriesIdentifier("A Corp.");//$NON-NLS-1$ ls1.setDataSet(orthoValues1); ls1.getLineAttributes().setColor(ColorDefinitionImpl.CREAM()); for(int i = 0; i < ls1.getMarkers().size(); i++) { ((Marker) ls1.getMarkers().get(i)).setType(MarkerType.TRIANGLE_LITERAL); ((Marker) ls1.getMarkers().get(i)).setSize(10); } ls1.getLabel().setVisible(true); SeriesDefinition sdY1 = SeriesDefinitionImpl.create(); sdY1.getSeriesPalette().shift(-2); yAxisPrimary.getSeriesDefinitions().add(sdY1); sdY1.getSeries().add(ls1); // Y-Serires (2) LineSeries ls2 = (LineSeries) LineSeriesImpl.create(); ls2.setSeriesIdentifier("B Corp.");//$NON-NLS-1$ ls2.setDataSet(orthoValues2); ls2.getLineAttributes().setColor(ColorDefinitionImpl.CREAM()); for(int i = 0; i < ls2.getMarkers().size(); i++) { ((Marker) ls2.getMarkers().get(i)).setType(MarkerType.CIRCLE_LITERAL); ((Marker) ls2.getMarkers().get(i)).setSize(10); } ls2.getLabel().setVisible(true); SeriesDefinition sdY2 = SeriesDefinitionImpl.create(); sdY2.getSeriesPalette().shift(-3); yAxis.getSeriesDefinitions().add(sdY2); sdY2.getSeries().add(ls2); return cwaBar; } public static void main(String[] args) { showGUI(); } /** * Auto-generated method to display this * org.eclipse.swt.widgets.Composite inside a new Shell. */ public static void showGUI() { Display display = Display.getDefault(); Shell shell = new Shell(display); ChartViewer viewer = new ChartViewer(shell, SWT.NO_BACKGROUND); Chart chart = MultipleYAxes.createMultipleYAxes(); viewer.setChart((ChartWithAxes) chart); shell.setLayout(new FillLayout()); shell.layout(); shell.pack(); shell.setSize(600, 450); shell.open(); while(!shell.isDisposed()) { if(!display.readAndDispatch()) display.sleep(); } } } //============================================================================= final class ChartViewer extends Composite implements PaintListener { private IDeviceRenderer renderer; private ChartWithAxes chart; private GeneratedChartState chartState; private Image buffer; private Rectangle clientArea; private ChartEngine engine; ChartViewer(Composite parent, int style) { super(parent, style); addPaintListener(this); try { PlatformConfig pf = new PlatformConfig(); pf.setProperty("STANDALONE", "true"); engine = ChartEngine.instance(pf); renderer = engine.getRenderer("dv.SWT");//$NON-NLS-1$ Assert.isNotNull(renderer, "Chart renderer is null"); } catch(ChartException ex) { System.err.println(ex); } } public final void paintControl(PaintEvent e) { if(chart == null) { return; } Rectangle cla = this.getClientArea(); if(clientArea == null || cla.width != clientArea.width || cla.height != clientArea.height) { clientArea = cla; drawToCachedImage(); } try { GC gc = e.gc; gc.drawImage(buffer, cla.x, cla.y); } catch(Exception ex) { System.err.println(ex); } } /** * Draws the chart onto the cached image in the area of the given * <code>Rectangle</code>. * * @param size * the area to draw */ private void drawToCachedImage() { GC gc = null; try { if(buffer != null) { buffer.dispose(); } buffer = new Image(Display.getCurrent(), clientArea.width, clientArea.height); gc = new GC(buffer); renderer.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, gc); buildChart(); IGenerator gr = engine.getGenerator(); gr.render(renderer, chartState); } catch(Exception ex) { System.err.println(ex); } finally { if(gc != null) { gc.dispose(); } } } /** * Builds the chart state. This method should be call when data has changed. */ private void buildChart() { Point size = getSize(); Bounds bo = BoundsImpl.create(0, 0, size.x, size.y); int resolution = renderer.getDisplayServer().getDpiResolution(); bo.scale(72d / resolution); try { IGenerator gr = engine.getGenerator(); chartState = gr.build(renderer.getDisplayServer(), chart, bo, null, null, null); } catch(ChartException ex) { System.err.println(ex); } } /** * @return the chart */ public ChartWithAxes getChart() { return chart; } /** * @param chart the chart to set */ public void setChart(ChartWithAxes chart) { this.chart = chart; } }

Files changed in fix:
chart/org.eclipse.birt.chart.engine/src/org/eclipse/birt/chart/computation/withaxes/PlotWith2DAxes.java