Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
PUBLIC CLOUD
PRIVATE CLOUD
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
Images on stacked bars
OhPun
I am trying to create a stacked bar chart where each section of the stack is filled with a color (no problem) or an image. This works quite well for pie and non-stacked bar charts. Attached is an image of a bar chart with images filling some of the bars (mostly on the right side). Basically I want to stack these bars by type.<br />
<br />
Currently, I am using scripting to color the stacked bars because I can not figure out how to set the default color palette. When I use an image, I get an error because the fill passed into beforeDrawDataPoint is already ColorDefinitonImpl. So, I either need to figure out how to set the palette or figure out how to get an EmbeddedImageImpl fill passed into beforeDrawDataPoint.<br />
<br />
Code for creating the stacked bar chart is below with comments.<br />
<br />
Each ArrayList of Fill (not the BIRT Fill) is placed into a single stacked bar, so all other bars are populated with zero for that item. This all works correctly, but I can not get the section of the stacked bar to fill with an image.<br />
<br />
public static void stackedbarChart(PPS pps, LinkedHashMap<String, ArrayList<Fill>> data)<br />
{<br />
if ((data == null) || (data.size() < 1))<br />
{<br />
// PPS.diagnose("Chart.barChart data is null"); //$NON-NLS-1$<br />
return; // nothing to chart<br />
}<br />
<br />
if (pps == null)<br />
{<br />
// PPS.diagnose("Chart.barChart pps is null"); //$NON-NLS-1$<br />
return;<br />
}<br />
<br />
String baseTag = chartType.getBaseTag(),<br />
tag = null;<br />
<br />
// Data Set<br />
// use data in order given<br />
<br />
String fileName = "Chart.png";<br />
<br />
ChartWithAxes cwaBar = ChartWithAxesImpl.create( );<br />
cwaBar.setDimension( ChartDimension.TWO_DIMENSIONAL_LITERAL );<br />
cwaBar.setType("Bar Chart"); //$NON-NLS-1$<br />
cwaBar.setSubType("Stacked"); //$NON-NLS-1$<br />
/* */<br />
StringBuilder script = new StringBuilder("importClass( com.performanceplanningsystem.site.setup.Setup );\n") //$NON-NLS-1$ <br />
.append("importClass( com.performanceplanningsystem.site.setup.Fill );\n") //$NON-NLS-1$<br />
.append("importClass( org.eclipse.swt.graphics.RGB );\n") //$NON-NLS-1$<br />
.append("importClass( com.performanceplanningsystem.ui.actions.Chart );\n") //$NON-NLS-1$<br />
.append("function beforeDrawDataPoint(dph, fill, icsc)\n") //$NON-NLS-1$<br />
.append("{\n") //$NON-NLS-1$<br />
.append(" importClass( java.lang.Iterable );\n") //$NON-NLS-1$<br />
.append(" importPackage( Packages.org.eclipse.birt.chart.model.attribute.impl );\n")<br />
.append(" dphSeriesName = dph.getSeriesDisplayValue();\n") //$NON-NLS-1$<br />
// .append(" Packages.java.lang.System.out.println(\"beforeDrawDataPoint \"+dphName);\n") //$NON-NLS-1$<br />
.append(" fillList = Setup.getPps().getSite().getSetup().getFillMap().values().toArray();\n" ) //$NON-NLS-1$<br />
.append(" for (i=0;i<fillList.length;i=i+1)\n") //$NON-NLS-1$<br />
.append(" {\n") //$NON-NLS-1$<br />
.append(" f = fillList
;\n") //$NON-NLS-1$<br />
.append(" desc = f.getName();\n") //$NON-NLS-1$<br />
.append(" if (dphSeriesName == desc) {\n") //$NON-NLS-1$<br />
// Chart.getFillImpl() returns either at ColorDefinitionImpl or EmbeddedImageImpl<br />
.append(" seriesFill = Chart.getFillImpl(f);\n")<br />
.append(" if(seriesFill instanceof ColorDefinitionImpl){\n")<br />
.append(" Packages.java.lang.System.out.println(\"beforeDrawDataPoint found series color\"+desc);\n") //$NON-NLS-1$<br />
.append(" fill.setType(seriesFill.getType());\n")<br />
.append(" fill.setRed(seriesFill.getRed());\n")<br />
.append(" fill.setGreen(seriesFill.getGreen());\n")<br />
.append(" fill.setBlue(seriesFill.getBlue());\n")<br />
.append(" fill.setTransparency(seriesFill.getTransparency());\n")<br />
.append(" return;\n")<br />
.append(" }\n")<br />
.append(" else if(seriesFill instanceof EmbeddedImageImpl){\n")<br />
.append(" Packages.java.lang.System.out.println(\"beforeDrawDataPoint found series image\"+desc);\n") //$NON-NLS-1$<br />
.append(" fill.setType(seriesFill.getType());\n")<br />
.append(" fill.setData(seriesFill.geData());\n")<br />
.append(" return;\n")<br />
.append(" }\n")<br />
.append(" }\n") //$NON-NLS-1$<br />
.append(" }\n") //$NON-NLS-1$<br />
.append("}\n") //$NON-NLS-1$<br />
.append("function beforeDrawSeries(series, isr, icsc)\n")<br />
.append("{\n") //$NON-NLS-1$<br />
.append("}\n") //$NON-NLS-1$<br />
;<br />
<br />
cwaBar.setScript(script.toString());<br />
/* */<br />
<br />
// set chart background color<br />
ColorDefinition backgroundColor = ColorDefinitionImpl.WHITE();<br />
backgroundColor.setTransparency(255);<br />
cwaBar.getBlock( ).setBackground(backgroundColor);<br />
<br />
// Plot<br />
Plot p = cwaBar.getPlot( );<br />
p.getClientArea( ).setBackground( backgroundColor.copyInstance() );<br />
p.getClientArea( ).getOutline( ).setVisible( false );<br />
p.getOutline( ).setVisible( false );<br />
<br />
// Line Attributes to black<br />
p.getOutline().setColor(ColorDefinitionImpl.BLACK());<br />
<br />
// Legend<br />
Legend lg = cwaBar.getLegend( );<br />
lg.setPosition( Position.BELOW_LITERAL ); // put legend at the bottom<br />
lg.setOrientation(Orientation.VERTICAL_LITERAL); // make legend items stacked<br />
lg.setItemType( LegendItemType.CATEGORIES_LITERAL );<br />
lg.setVisible(false);<br />
// not relevant since legend is invisible<br />
lg.getClientArea( ).getOutline( ).setVisible( true );<br />
lg.getTitle( ).setVisible( false );<br />
lg.setShowPercent(true);<br />
org.eclipse.birt.chart.model.attribute.Text t = lg.getText();<br />
FontDefinition fd = t.getFont();<br />
fd.setName("Courier"); //$NON-NLS-1$<br />
fd.setBold(true);<br />
lg.updateLayout(cwaBar);<br />
// end not relevant legend<br />
<br />
// X-Axis<br />
Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes()[0];<br />
xAxisPrimary.setType(AxisType.TEXT_LITERAL);<br />
xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.BELOW_LITERAL);<br />
xAxisPrimary.getOrigin().setType(IntersectionType.MIN_LITERAL);<br />
xAxisPrimary.getLabel().getCaption().getFont().setBold(true);<br />
xAxisPrimary.getLabel().getCaption().getFont().setRotation(-30);<br />
<br />
xAxisPrimary.getTitle().setVisible(true); <br />
<br />
tag = new StringBuilder(baseTag).append(".SeriesTitle.total").toString(); //$NON-NLS-1$<br />
String seriesId = PPS.getPpsResources().getString(tag);<br />
xAxisPrimary.getTitle().getCaption().setValue(seriesId);<br />
<br />
// Y-Axis<br />
Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary);<br />
yAxisPrimary.getMajorGrid().setTickStyle(TickStyle.LEFT_LITERAL);<br />
yAxisPrimary.setType(AxisType.LINEAR_LITERAL);<br />
yAxisPrimary.getLabel().getCaption().getFont().setBold(true);<br />
yAxisPrimary.getTitle().setVisible(false);<br />
//yAxisPrimary.getTitle().getCaption().setValue(chartSpec.getyAxisTitle());<br />
<br />
<br />
String[] categories = new String[data.size()];<br />
data.keySet().toArray(categories);<br />
<br />
String title = null;<br />
<br />
Setup setup = Setup.getPps().getSite().getSetup();<br />
PointNum valueFactor = PointNum.ONETHOUSAND.multiply(PointNum.ONETHOUSAND);<br />
tag = new StringBuilder(baseTag).append(".charttitle").toString(); //$NON-NLS-1$<br />
title = PPS.getPpsResources().getMessage(tag, new Object[] { setup.formatPointNum(valueFactor, 0, 0, false) }); <br />
<br />
cwaBar.getTitle( )<br />
.getLabel( )<br />
.getCaption( )<br />
.setValue(title); <br />
cwaBar.getTitle( ).getOutline( ).setVisible( false );<br />
TextDataSet categoryValues = TextDataSetImpl.create(categories);<br />
<br />
// X-Series<br />
SeriesDefinition sdX = SeriesDefinitionImpl.create( );<br />
xAxisPrimary.getSeriesDefinitions().add(sdX);<br />
Series seCategory = SeriesImpl.create();<br />
seCategory.setDataSet(categoryValues);<br />
sdX.getSeries().add(seCategory);<br />
<br />
int dataCount = 0;<br />
for (ArrayList<Fill> fills: data.values())<br />
{<br />
for (Fill fill: fills)<br />
{<br />
MarketData marketData = fill.getMarketData();<br />
if (marketData != null)<br />
{ <br />
double[] values = new double[data.size()];<br />
// populate columns with zero<br />
Arrays.fill(values, 0.0);<br />
PointNum totalValue = fill.getMarketData().calcTotalValue();<br />
if (totalValue != null)<br />
{<br />
values[dataCount] = totalValue.divide(valueFactor).doubleValue();<br />
}<br />
<br />
<br />
Series stackedSeries = (BarSeries) BarSeriesImpl.create();<br />
stackedSeries.setSeriesIdentifier(fill.getName());<br />
stackedSeries.setStacked(true);<br />
DataSet ds = NumberDataSetImpl.create(values);<br />
stackedSeries.setDataSet(ds);<br />
<br />
SeriesDefinition sdVal = SeriesDefinitionImpl.create(); <br />
sdVal.getSeriesPalette().shift(0);<br />
yAxisPrimary.getSeriesDefinitions().add(sdVal); <br />
<br />
// attempting to set the color or image for the series, has no effect on the chart<br />
// setting color or image for number of columns also has no effect<br />
setSeriesDefinitionPattern(sdVal, fill);<br />
<br />
sdVal.getSeries().add(stackedSeries); <br />
} // end has market data<br />
} // end for each fill<br />
<br />
dataCount++;<br />
}<br />
<br />
final String chartFileName = renderChart((org.eclipse.birt.chart.model.Chart) cwaBar, fileName);<br />
<br />
}
Find more posts tagged with
Comments
mwilliams
Maybe this devShare entry will help with setting the palette:
http://www.birt-exchange.org/org/devshare/designing-birt-reports/1437-birt-palette-examples/
OhPun
I have looked at that page. It tells me that I can have different fill types depending on the palette. Unfortunately, a chart with axes (bar chart) does does not have cwaBar.getSeriesDefinitions(), so how do you set the palette?
I am setting the palette for each individual series, but that seems to have no effect.
mwilliams
On a chart with axes, you grab the Series Definitions from the xAxis:
importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl);
var xAxis = chart.getAxes().get(0);
var sd = xAxis.getSeriesDefinitions().get(0);
I believe you should only have to set the palette for the first series. The very last example from the blog that the above link points to shows this. This isn't working for you? Let me know.
OhPun
I have twelve bar series that I add to the y axis. Each series has four values. When I set the x axis Series Definition, each of the four bars is colored with the first four colors. The remaining eight colors are ignored. The individual sections are not individually colored.<br />
<br />
1) Should I be making four series with twelve values? then setting the x axis Series Definition?<br />
<br />
2) I suppose if I set the x axis Series Definition to embedded image, then I could replace them in the scripting with embedded images, forcing the colors to be embedded images too.<br />
<br />
3) In the code of the original post, I changed <br />
<pre class='_prettyXprint _lang-auto _linenums:0'>lg.setItemType( LegendItemType.CATEGORIES_LITERAL );</pre>
to<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>lg.setItemType( LegendItemType.SERIES_LITERAL );</pre>
<br />
Attached is the chart I am currently producing with scripting. The data is complete and utter garbage, but correctly graphed garbage. It all works with colors. Unfortunately it does not work with embedded images.
OhPun
<blockquote class='ipsBlockquote' data-author="'OhPun'" data-cid="93461" data-time="1325689775" data-date="04 January 2012 - 08:09 AM"><p>
<br />
2) I suppose if I set the x axis Series Definition to embedded image, then I could replace them in the scripting with embedded images, forcing the colors to be embedded images too.<br />
<br /></p></blockquote>
<br />
Option 2 does not work. Even when I set the x axis Series Definition to EmbeddedImageImpl, the fills that are passed into beforeDrawDataPoint are ColorDefinitionImpl.
OhPun
Answer: no scripting is needed.<br />
<br />
Before creating any BarSeries, make one SeriesDefinitionImpl, clear the SeriesPalette, add it to the y axis<br />
<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>SeriesDefinition sdVal = SeriesDefinitionImpl.create();
sdVal.getSeriesPalette().getEntries().clear();
yAxisPrimary.getSeriesDefinitions().add(sdVal);</pre>
<br />
for each series ('data' in this example)<br />
{<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>BarSeries stackedSeries = (BarSeries) BarSeriesImpl.create();
String desc = data.getDescription(); // series description
double[] values = data.getValues(); // series values
stackedSeries.setSeriesIdentifier(desc);
stackedSeries.setStacked(true);
DataSet ds = NumberDataSetImpl.create(values);
stackedSeries.setDataSet(ds);
// add ColorDefinitionImpl or EmbeddedImageImpl to sdVal.getSeriesPalette().getEntries()
sdVal.getSeriesPalette().getEntries().add(data.getFillImpl());
sdVal.getSeries().add(stackedSeries);</pre>
}
mwilliams
Great! Glad you found a solution. Sorry for the delayed response, the forums have been crazy so far this new year! Let us know whenever you have questions!
mwilliams
Would you mind creating a simple example of how to get images onto bars in a chart and putting it in the devShare? It could be a great help to other users!