public
Created

Wicket and JFreeChart integration including image map for tooltips and clickable graph

  • Download Gist
DynamicImageMap.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
 
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxCallDecorator;
import org.apache.wicket.ajax.calldecorator.CancelEventIfNoAjaxDecorator;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.jfree.chart.entity.ChartEntity;
 
import java.util.Collection;
import java.util.Iterator;
 
/**
* Wicket markup container that produces an image map dynamically
* from the given model
*
* @author Jonny Wray
*/
public abstract class DynamicImageMap extends WebMarkupContainer {
 
private String mapName;
 
public DynamicImageMap(String id, String mapName, IModel<Collection<ChartEntity>> model){
super(id, model);
this.mapName = mapName;
RefreshingView mapAreas = new RefreshingView("areas", model){
 
@Override
protected Iterator getItemModels() {
Collection<ChartEntity> chartEntityCollection = (Collection<ChartEntity>)getDefaultModelObject();
return new ModelIteratorAdapter(chartEntityCollection.iterator()){
@Override
protected IModel model(Object object) {
return new Model((ChartEntity)object);
}
};
}
 
@Override
protected void populateItem(Item item) {
final ChartEntity entity = (ChartEntity)item.getModelObject();
WebMarkupContainer area = new WebMarkupContainer("area"){
 
@Override
protected void onComponentTag(final ComponentTag tag){
super.onComponentTag(tag);
assert tag.getName().equals("area");
tag.put("shape", entity.getShapeType());
tag.put("coords", entity.getShapeCoords());
tag.put("href", "#");
String tooltipText = entity.getToolTipText();
if(tooltipText != null && !tooltipText.isEmpty()){
tag.put("title", tooltipText);
}
}
};
area.add(new AjaxEventBehavior("onclick"){
private static final long serialVersionUID = 2615093257359874075L;
 
@Override
protected void onEvent(AjaxRequestTarget target) {
onClickCallback(target, entity);
}
 
protected IAjaxCallDecorator getAjaxCallDecorator(){
return new CancelEventIfNoAjaxDecorator();
}
 
});
item.add(area);
}
};
add(mapAreas);
}
 
public abstract void onClickCallback(AjaxRequestTarget target, ChartEntity entity);
 
@Override
protected void onComponentTag(final ComponentTag tag){
super.onComponentTag(tag);
assert tag.getName().equals("map");
tag.put("name", mapName);
}
}
JFreeChartRenderingBean.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 
import org.apache.wicket.markup.html.image.resource.BufferedDynamicImageResource;
import org.apache.wicket.markup.html.image.resource.DynamicImageResource;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.EntityCollection;
 
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
 
/**
* Bean that holds the information and logic needed to render
* a JFreeChart to an image. Used as a model object to enable
* dynamic redrawing of an chart image.
*
* @author Jonny Wray
*/
public class JFreeChartRenderingBean implements Serializable{
private ChartRenderingInfo renderingInfo = new ChartRenderingInfo();
private BufferedDynamicImageResource imageResource;
private JFreeChart chart;
private int width;
private int height;
 
/**
* Construct the rendering bean
*
* @param chart The chart to render
* @param width The width to render to
* @param height The height to render to
*/
public JFreeChartRenderingBean(JFreeChart chart, int width, int height){
this.chart = chart;
this.width = width;
this.height = height;
}
 
public DynamicImageResource getImageResource(){
if(imageResource == null){
renderingInfo.clear();
BufferedImage image = chart.createBufferedImage(width, height, renderingInfo);
imageResource = new BufferedDynamicImageResource();
imageResource.setImage(image);
}
return imageResource;
}
 
public Collection<ChartEntity> getChartEntities(){
if(imageResource == null){
getImageResource(); // Force the image to be rendered
}
Collection<ChartEntity> chartEntities = new ArrayList<ChartEntity>();
EntityCollection entities = renderingInfo.getEntityCollection();
if (entities != null) {
int count = entities.getEntityCount();
for (int i = count - 1; i >= 0; i--) {
ChartEntity entity = entities.getEntity(i);
chartEntities.add(entity);
}
}
return chartEntities;
}
}
MappedJFreeChartPanel.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" xml:lang="en" lang="en">
<wicket:panel>
<span>
<img style="vertical-align: middle;" wicket:id="image" />
<map wicket:id="imageMap" >
<span wicket:id="areas">
<area wicket:id="area" />
</span>
</map>
</span>
</wicket:panel>
</html>
MappedJFreeChartPanel.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.image.NonCachingImage;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.jfree.chart.entity.ChartEntity;
 
import java.util.UUID;
 
/**
* Wicket panel that includes a JFreeChart as an image with an
* associated image map used for tooltips and clicks.
*
* @author Jonny Wray
*/
public class MappedJFreeChartPanel extends Panel {
 
public MappedJFreeChartPanel(final String id, final IModel<JFreeChartRenderingBean> model){
super(id, model);
String mapName = getPath() + UUID.randomUUID().toString(); // UUID allows use in a repeater
 
NonCachingImage chartImage = new NonCachingImage("image", new PropertyModel(model, "imageResource"));
chartImage.add(new AttributeModifier("usemap", true, new Model("#"+mapName)));
add(chartImage);
DynamicImageMap imageMap = new DynamicImageMap("imageMap", mapName, new PropertyModel(model, "chartEntities")){
@Override
public void onClickCallback(AjaxRequestTarget target, ChartEntity entity) {
onClick(target, entity);
}
};
add(imageMap);
}
 
/**
* Do nothing implementation of an onClick callback for a chart entity. Override to
* implement Ajax onclick functionality
*
* @param target The Ajax request
* @param entity The chart entity clicked on
*/
protected void onClick(AjaxRequestTarget target, ChartEntity entity){
 
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.