Home » Eclipse Projects » BIRT » [chart] with multiple categories (on x)
| |
| Re: [chart] with multiple categories (on x) [message #908875 is a reply to message #908607] |
Thu, 06 September 2012 02:46   |
moritz du Messages: 98 Registered: February 2010 |
Member |
|
|
thx jason,
In my case the tables are self made and table representation in web, pdf, excel, csv is done. Now i only need the chart. First we tried jfreechart but their svg output is unusable (no interactivity).
thx to you i can create charts from all tables as specified. the only problem remaining is the formatting of x labels for pivot tables. they have up to 3 dimension on one axis and concatenating all dimensions will be too much (the real label are much longer than in the example). in most cases the regional dimension should be separated (R3, R8 in example).
So an example how to achieve the label moving will be great.
[Updated on: Thu, 06 September 2012 03:14] Report message to a moderator
|
|
| | |
| Re: [chart] with multiple categories (on x) [message #909721 is a reply to message #909445] |
Fri, 07 September 2012 12:38   |
Jason Weathersby Messages: 9167 Registered: July 2009 |
Senior Member |

|
|
If you imported the report, you should have layout, Master Page, Script, XML Source and Preview tabs. If you create a new report do you get those? You can always select the xml tab and copy and paste the report contents in. Specifically this was done with chart script. Select the chart and click on the script tab:
last = "";
function beforeDrawAxisLabel( axis, label, icsc )
{
importPackage(
Packages.org.eclipse.birt.chart.model.attribute.impl );
importPackage(
Packages.org.eclipse.birt.chart.model.attribute );
if( axis.getType() == AxisType.TEXT_LITERAL ){
var cp =label.getCaption().getValue();
if( cp.substr(0,2) == last ){
label.getCaption().setValue(cp.substr( (cp.length()-2)));
}else{
label.getCaption().setValue(cp.substr( (cp.length()-2))+"\n\r "+cp.substr(0,2));
}
last = cp.substr(0,2);
}
}
It uses a beforeDrawAxisLabel script. When using the Chart API you can set a script like:
ChartWithAxes cwaBar = ChartWithAxesImpl.create( );
cwaBar.setScript( "function afterDataSetFilled( series, idsp,Iicsc )"
+ "{importPackage(Packages.java.lang); "
+ "if (series.getLabel().isVisible() == true)"
+ "{System.out.println(\"ok\");} "
+ "else"
+ "{System.out.println(\"false\");}} "
);
Jason
Jason Weathersby
BIRT Exchange
|
|
| | | | | |
| Re: [chart] with multiple categories (on x) [message #912470 is a reply to message #911687] |
Thu, 13 September 2012 12:31   |
Jason Weathersby Messages: 9167 Registered: July 2009 |
Senior Member |

|
|
The afterDataSetFilled was just an example of one event that you could override. You need to put the script in a Java String and use the setScript to set in on the chart. For a list of all events look at this post:
http://birtworld.blogspot.com/2010/08/birt-charting-scripting-overview.html
You could also use setScript to set a fully qualified classname that extends the ChartEventHandlerAdapter class. Like:
import org.eclipse.birt.chart.model.attribute.AxisType;
import org.eclipse.birt.chart.model.component.Axis;
import org.eclipse.birt.chart.model.component.Label;
import org.eclipse.birt.chart.script.ChartEventHandlerAdapter;
import org.eclipse.birt.chart.script.IChartScriptContext;
/**
*
*/
public class AxisScript extends ChartEventHandlerAdapter
{
/*
* (non-Javadoc)
*
* @see org.eclipse.birt.chart.script.IChartItemScriptHandler#beforeDrawAxisLabel(org.eclipse.birt.chart.model.component.Axis,
* org.eclipse.birt.chart.model.component.Label,
* org.eclipse.birt.chart.script.IChartScriptContext)
*/
public void beforeDrawAxisLabel( Axis axis, Label label,
IChartScriptContext icsc )
{
if (axis.getType() == AxisType.TEXT_LITERAL)
{
label.getCaption( ).getColor( ).set( 140, 198, 62 );
}else
{
label.getCaption().getColor( ).set( 208, 32, 0);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.birt.chart.script.IChartItemScriptHandler#beforeDrawAxisTitle(org.eclipse.birt.chart.model.component.Axis,
* org.eclipse.birt.chart.model.component.Label,
* org.eclipse.birt.chart.script.IChartScriptContext)
*/
public void beforeDrawAxisTitle( Axis axis, Label label,
IChartScriptContext icsc )
{
if (axis.getType() == AxisType.TEXT_LITERAL)
{
label.getCaption( ).getColor( ).set( 140, 198, 62 );
}else
{
label.getCaption().getColor( ).set( 208, 32, 0);
}
}
}
and in your code you could do chart.setScript("AxisScript"); Note that this name you be fully qualified. In my example I did not have AxisScript in a package.
Jason
Jason Weathersby
BIRT Exchange
|
|
| | |
| Re: [chart] with multiple categories (on x) [message #916986 is a reply to message #916847] |
Wed, 19 September 2012 13:57   |
Jason Weathersby Messages: 9167 Registered: July 2009 |
Senior Member |

|
|
In the report example I use row["FILIAL"]+" Week "+row["weekno"] as the expression in the birt design. This would result in category value of something like "SF Week 19". The script splits this up. When the chart engine is used in the BIRT designer it implements its on data set processor that does aggregations, etc before passing the data to the chart engine. So you need to either modify your data before passing it to the chart or implement your own data set process. Here is an example of that:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import org.eclipse.birt.chart.api.ChartEngine;
import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.device.IDisplayServer;
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.IDataRowExpressionEvaluator;
import org.eclipse.birt.chart.factory.IGenerator;
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.ChartWithoutAxes;
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.ChartDimension;
import org.eclipse.birt.chart.model.attribute.DataType;
import org.eclipse.birt.chart.model.attribute.SortOption;
import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.birt.chart.model.attribute.impl.GradientImpl;
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.BaseSampleData;
import org.eclipse.birt.chart.model.data.DataFactory;
import org.eclipse.birt.chart.model.data.OrthogonalSampleData;
import org.eclipse.birt.chart.model.data.Query;
import org.eclipse.birt.chart.model.data.SampleData;
import org.eclipse.birt.chart.model.data.SeriesDefinition;
import org.eclipse.birt.chart.model.data.impl.QueryImpl;
import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl;
import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl;
import org.eclipse.birt.chart.model.impl.ChartWithoutAxesImpl;
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.PieSeries;
import org.eclipse.birt.chart.model.type.impl.LineSeriesImpl;
import org.eclipse.birt.chart.model.type.impl.PieSeriesImpl;
import org.eclipse.birt.core.framework.PlatformConfig;
/**
* Test decription:
* </p>
* Chart script: afterDataSetFilled()
* </p>
*/
public class AfterDatasetFilled
{
private static String OUTPUT = "output/DataRowEvaluator.png";
/**
* The swing rendering device
*/
private IDeviceRenderer dRenderer = null;
private IDisplayServer dServer = null;
private GeneratedChartState gcs = null;
private IGenerator gr = null;
/**
* A chart model instance
*/
private Chart cm = null;
/**
* execute application
*
* @param args
*/
public static void main( String[] args )
{
new AfterDatasetFilled( );
System.out.println("finished");
System.exit(0);
}
/**
* Constructor
*/
public AfterDatasetFilled( )
{
PlatformConfig pf = new PlatformConfig();
pf.setProperty("STANDALONE", true);
//Returns a singleton instance of the Chart Engine
ChartEngine ce = ChartEngine.instance(pf);
//Returns a singleton instance of the Generator
gr = ce.getGenerator();
try {
//device renderers for dv.SWT, dv.PNG, dv.JPG
//dv.PDF, dv.SVG, dv.SWING, dv.PNG24, div.BMP
dRenderer = ce.getRenderer("dv.PNG");
dServer = dRenderer.getDisplayServer();
} catch (Exception ex) {
ex.printStackTrace();
}
cm = createChart( );
bindGroupingData( cm );
BufferedImage img = new BufferedImage(
600,
600,
BufferedImage.TYPE_INT_ARGB );
Graphics g = img.getGraphics( );
Graphics2D g2d = (Graphics2D) g;
dRenderer.setProperty( IDeviceRenderer.GRAPHICS_CONTEXT, g2d );
dRenderer.setProperty( IDeviceRenderer.FILE_IDENTIFIER, OUTPUT ); //$NON-NLS-1$
Bounds bo = BoundsImpl.create( 0, 0, 600, 600 );
bo.scale( 72d / dRenderer.getDisplayServer( ).getDpiResolution( ) );
try
{
gcs = gr.build(
dServer,
cm,
bo,
null,
null,
null );
gr.render( dRenderer, gcs );
}
catch ( ChartException e )
{
// TODO Auto-generated catch block
e.printStackTrace( );
}
}
public Chart GetChartModel(){
return cm;
}
private void bindGroupingData( Chart chart )
{
//IDataRowExpressionEvaluator
// close, evaluate, first, and next
// Data Set
final Object[][] data =
new Object[][]
{{"x1", new Integer( 1 ), "g1"},
{"x1", new Integer( 2 ), "g2"},
{"x1", new Integer( 3 ), "g1"},
{"x1", new Integer( 4 ), "g3"},
{"x1", new Integer( 5 ), "g2"},
{"x2", new Integer( 6 ), "g1"},
{"x2", new Integer( 7 ), "g3"},
{"x2", new Integer( 8 ), "g2"},
{"x2", new Integer( 9 ), "g2"},
{"x0", new Integer( 0 ), "g2"},};
try
{
//Binds data to chart model
gr.bindData( new IDataRowExpressionEvaluator( ) {
int idx = 0;
public void close( )
{
}
public Object evaluate( String expression )
{
if ( "X".equals( expression ) )
{
return data[idx][0];
}
else if ( "Y".equals( expression ) )
{
return data[idx][1];
}
else if ( "G".equals( expression ) )
{
return data[idx][2];
}
return null;
}
public Object evaluateGlobal( String expression )
{
return evaluate( expression );
}
public boolean first( )
{
idx = 0;
return true;
}
public boolean next( )
{
idx++;
return ( idx < 9 );
}
}, chart, new RunTimeContext( ) );
}
catch ( ChartException e )
{
e.printStackTrace( );
}
}
private Chart createChart( )
{
ChartWithAxes cwaBar = ChartWithAxesImpl.create( );
// X-Axis
Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes( )[0];
xAxisPrimary.setType( AxisType.TEXT_LITERAL );
// Y-Axis
Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis( xAxisPrimary );
yAxisPrimary.setType( AxisType.LINEAR_LITERAL );
// X-Series
Series seCategory = SeriesImpl.create( );
Query xQ = QueryImpl.create( "G" );
seCategory.getDataDefinition( ).add( xQ );
SeriesDefinition sdX = SeriesDefinitionImpl.create( );
xAxisPrimary.getSeriesDefinitions( ).add( sdX );
sdX.getSeries( ).add( seCategory );
// -------------------------------------------------------------
sdX.setSorting( SortOption.ASCENDING_LITERAL );
sdX.getGrouping( ).setEnabled( true );
sdX.getGrouping( ).setGroupType( DataType.TEXT_LITERAL );
sdX.getGrouping( ).setAggregateExpression( "Sum" );
sdX.getGrouping( ).setGroupingInterval( 0 );
// -------------------------------------------------------------
// Y-Series
LineSeries ls = (LineSeries) LineSeriesImpl.create( );
ls.getLabel( ).setVisible( true );
Query yQ = QueryImpl.create( "Y" );
ls.getDataDefinition( ).add( yQ );
SeriesDefinition sdY = SeriesDefinitionImpl.create( );
Query query = QueryImpl.create( "X" );//$NON-NLS-1$
sdY.setQuery( query );
yAxisPrimary.getSeriesDefinitions( ).add( sdY );
sdY.getSeriesPalette( ).shift( 0 );
sdY.getSeries( ).add( ls );
return cwaBar;
}
}
Jason
Jason Weathersby
BIRT Exchange
|
|
| |
| Re: [chart] with multiple categories (on x) [message #917478 is a reply to message #908333] |
Thu, 20 September 2012 01:54   |
moritz du Messages: 98 Registered: February 2010 |
Member |
|
|
thx jason
i came to work, the first thing i did was pressing f5 on this thread's tab and i am glad to see your answer.
i just tired your example it yields an line chart with 2 lines. But i don't get the link to your "adjustxaxislabelsmultiline.rptdesign" report.
I probably don't understand "In the report example I use row["FILIAL"]+" Week "+row["weekno"] as the expression in the birt design."
Or how to do this in java. In this example it seems that each bar has 2 labels given via separate array indexes. And your "beforeDrawAxisLabel" moves the second label - the filial name. I don't really understand the moving - or how it would look without this script. i guess "var cp =label.getCaption().getValue();" will only return the filial name not the week number?
(i attached the output as pdf, as i mentioned some day ago i can't preview the report nor use "Web Viewer", only the other file formats work. i also attached the source - it was converted to birt 4.2 by eclipse - don't no if this changed something else)
so at the moment my problem is the same - how to get a bar chart like "adjustxaxislabelsmultiline" with java. and if i got this i could try to apply your script. (but probably i misunderstood some other things?)
[Updated on: Thu, 20 September 2012 03:05] Report message to a moderator
|
|
|
| Re: [chart] with multiple categories (on x) [message #917956 is a reply to message #917478] |
Thu, 20 September 2012 11:42   |
Jason Weathersby Messages: 9167 Registered: July 2009 |
Senior Member |

|
|
The x-axis does not have two labels, it has one that that the script splits into two lines. From a Java perspective this would look like:
TextDataSet dsStringValue = TextDataSetImpl.create( new String[]{
"SF Week 19", "SF Week 20", "KF Week 19", "KF Week 20", "PF Week 19", "PF Week 20" } );
Series seCategory = SeriesImpl.create( );
seCategory.setDataSet( dsStringValue );
So this script:
last = "";
function beforeDrawAxisLabel( axis, label, icsc )
{
importPackage(
Packages.org.eclipse.birt.chart.model.attribute.impl );
importPackage(
Packages.org.eclipse.birt.chart.model.attribute );
if( axis.getType() == AxisType.TEXT_LITERAL ){
var cp =label.getCaption().getValue();
if( cp.substr(0,2) == last ){
label.getCaption().setValue(cp.substr( (cp.length()-2)));
}else{
label.getCaption().setValue(cp.substr( (cp.length()-2))+"\n\r "+cp.substr(0,2));
}
last = cp.substr(0,2);
}
}
So for the first label that comes in this line:
label.getCaption().setValue(cp.substr( (cp.length()-2))+"\n\r "+cp.substr(0,2));
puts the week number on top and the Fial number on the bottom. The second label will just put the week number on top:
label.getCaption().setValue(cp.substr( (cp.length()-2)));
The reason I posted the afterdatasetfilled example was to show you how the data for a chart could be made to be dynamic if you wanted it to.
Jason
Jason Weathersby
BIRT Exchange
|
|
| |
| Re: [chart] with multiple categories (on x) [message #919079 is a reply to message #918612] |
Fri, 21 September 2012 13:03   |
Jason Weathersby Messages: 9167 Registered: July 2009 |
Senior Member |

|
|
public static final Chart createBarChart( )
{
ChartWithAxes cwaBar = ChartWithAxesImpl.create( );
// Chart Type
cwaBar.setType( "Bar Chart" );
cwaBar.setScript("AxisScriptSplit");
cwaBar.getTitle().setVisible(false);
cwaBar.getBlock( ).setBackground( ColorDefinitionImpl.WHITE( ) );
// Legend
Legend lg = cwaBar.getLegend( );
lg.setVisible( false );
// X-Axis
Axis xAxisPrimary = ( (ChartWithAxesImpl) cwaBar ).getPrimaryBaseAxes( )[0];
xAxisPrimary.getTitle( ).setVisible( false );
xAxisPrimary.setType( AxisType.TEXT_LITERAL );
xAxisPrimary.getOrigin( ).setType( IntersectionType.VALUE_LITERAL );
//xAxisPrimary.getLabel( ).getCaption( ).setColor(
// ColorDefinitionImpl.GREEN( ).darker( ) );
xAxisPrimary.getLabel( ).getCaption( ).getFont( ).setSize(6);
xAxisPrimary.setLabelSpan(30);
// Y-Axis
Axis yAxisPrimary = ( (ChartWithAxesImpl) cwaBar )
.getPrimaryOrthogonalAxis( xAxisPrimary );
yAxisPrimary.getLabel( ).getCaption( ).setValue( "Sales Growth" ); //$NON-NLS-1$
yAxisPrimary.getLabel( ).getCaption( ).setColor(
ColorDefinitionImpl.BLUE( ) );
yAxisPrimary.getLabel( ).getCaption( ).getFont( ).setSize(6);
yAxisPrimary.getTitle( ).setVisible( false );
yAxisPrimary.setType( AxisType.LINEAR_LITERAL );
yAxisPrimary.getOrigin( ).setType( IntersectionType.VALUE_LITERAL );
TextDataSet dsStringValue = TextDataSetImpl.create( new String[]{
"SF Week 19", "SF Week 20", "KF Week 19", "KF Week 20", "PF Week 19", "PF Week 20" } );
NumberDataSet dsNumericValues1 = NumberDataSetImpl
.create( new double[]{43.26, 56.55, 75.25, 47.56, 55.55, 32.1} );
// X-Series
Series seBase = SeriesImpl.create( );
seBase.setDataSet( dsStringValue );
SeriesDefinition sdX = SeriesDefinitionImpl.create( );
xAxisPrimary.getSeriesDefinitions( ).add( sdX );
sdX.getSeries( ).add( seBase );
// Y-Series
BarSeries bs = (BarSeries) BarSeriesImpl.create( );
bs.getLabel( ).getCaption( ).setColor( ColorDefinitionImpl.RED( ) );
bs.getLabel( ).setBackground( ColorDefinitionImpl.CYAN( ) );
bs.getLabel( ).setVisible( true );
bs.setDataSet( dsNumericValues1 );
bs.setStacked( false );
SeriesDefinition sdY = SeriesDefinitionImpl.create( );
yAxisPrimary.getSeriesDefinitions( ).add( sdY );
sdY.getSeriesPalette( ).update( ColorDefinitionImpl.GREEN( ) );
sdY.getSeries( ).add( bs );
return cwaBar;
}
Use the following for the AxisScriptSplit class:
import org.eclipse.birt.chart.model.attribute.AxisType;
import org.eclipse.birt.chart.model.component.Axis;
import org.eclipse.birt.chart.model.component.Label;
import org.eclipse.birt.chart.script.ChartEventHandlerAdapter;
import org.eclipse.birt.chart.script.IChartScriptContext;
/**
*
*/
public class AxisScriptSplit extends ChartEventHandlerAdapter
{
String last ="";
public void beforeDrawAxisLabel( Axis axis, Label label,
IChartScriptContext icsc )
{
if (axis.getType() == AxisType.TEXT_LITERAL)
{
String cp =label.getCaption().getValue();
if( cp.substring(0,2).compareToIgnoreCase(last) == 0){
label.getCaption().setValue(cp.substring( (cp.length()-2)));
}else{
label.getCaption().setValue(cp.substring( (cp.length()-2))+"\n\r "+cp.substring(0,2));
last = cp.substring(0,2);
}
}
}
}
If you put the AxisScriptClass in a package make sure to change the setScript method to include the package name. A pic out the output is attached.
Jason Weathersby
BIRT Exchange
|
|
| | | | | |
Goto Forum:
Current Time: Wed May 22 23:48:48 EDT 2013
Powered by FUDForum. Page generated in 0.02404 seconds
|