Skip to content

Instantly share code, notes, and snippets.

@jonnywray
Created October 26, 2010 16:55
Show Gist options
  • Save jonnywray/647285 to your computer and use it in GitHub Desktop.
Save jonnywray/647285 to your computer and use it in GitHub Desktop.
Wicket and JFreeChart integration including image map for tooltips and clickable graph
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);
}
}
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;
}
}
<!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>
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){
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment