package org.activityinfo.server.report.renderer.ppt;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.code.appengine.awt.Dimension;
import com.google.code.appengine.awt.Rectangle;
import com.google.inject.Inject;
import org.activityinfo.legacy.shared.reports.content.BubbleMapMarker;
import org.activityinfo.legacy.shared.reports.content.IconMapMarker;
import org.activityinfo.legacy.shared.reports.content.MapMarker;
import org.activityinfo.legacy.shared.reports.model.MapReportElement;
import org.activityinfo.server.geo.AdminGeometryProvider;
import org.activityinfo.server.report.generator.MapIconPath;
import org.activityinfo.server.report.generator.map.IconRectCalculator;
import org.activityinfo.server.report.renderer.image.ImageMapRenderer;
import org.activityinfo.server.report.util.ColorUtil;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.hslf.model.AutoShape;
import org.apache.poi.hslf.model.Picture;
import org.apache.poi.hslf.model.ShapeTypes;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author Alex Bertram
*/
public class PPTMapRenderer extends ImageMapRenderer {
@Inject
public PPTMapRenderer(AdminGeometryProvider geometryProvider, @MapIconPath String mapIconPath) {
super(geometryProvider, mapIconPath);
}
@Override
public void render(MapReportElement element, OutputStream stream) throws IOException {
// create a new empty slide show
SlideShow ppt = new SlideShow();
Dimension pageSize = computePageSize(element);
ppt.setPageSize(pageSize);
render(element, ppt);
// write to stream
ppt.write(stream);
}
public void render(MapReportElement element, SlideShow ppt) throws IOException {
// add first slide
Slide slide = ppt.createSlide();
// calculate map offset
Dimension pageSize = ppt.getPageSize();
int offsetX = ((int) pageSize.getWidth() - element.getWidth()) / 2;
int offsetY = ((int) pageSize.getHeight() - element.getHeight()) / 2;
// add the map background image
drawBasemap(element, new PPTTileHandler(ppt, slide));
// keep a list of map icons
Map<String, Integer> iconPictureIndex = new HashMap<String, Integer>();
// Add the indicator markers to the slide as shapes
for (MapMarker marker : element.getContent().getMarkers()) {
if (inView(element, marker)) {
if (marker instanceof IconMapMarker) {
addIconMarker(ppt, slide, offsetX, offsetY, iconPictureIndex, (IconMapMarker) marker);
} else if (marker instanceof BubbleMapMarker) {
addBubble(slide, offsetX, offsetY, (BubbleMapMarker) marker);
}
}
}
}
private boolean inView(MapReportElement element, MapMarker marker) {
return (marker.getX() + marker.getSize()) > 0 &&
(marker.getY() + marker.getSize()) > 0 &&
(marker.getX() - marker.getSize()) < element.getWidth() &&
(marker.getY() - marker.getSize()) < element.getHeight();
}
private void addBubble(Slide slide, int offsetX, int offsetY, BubbleMapMarker marker) {
AutoShape shape = new AutoShape(ShapeTypes.Ellipse);
shape.setAnchor(new Rectangle(offsetX + marker.getX() - marker.getRadius(),
offsetY + marker.getY() - marker.getRadius(),
marker.getRadius() * 2,
marker.getRadius() * 2));
shape.setFillColor(ColorUtil.colorFromString(marker.getColor()));
shape.setEscherProperty(EscherProperties.FILL__FILLOPACITY, 49087);
shape.setLineColor(bubbleStrokeColor(ColorUtil.toInteger(marker.getColor())));
slide.addShape(shape);
}
private void addIconMarker(SlideShow ppt,
Slide slide,
int offsetX,
int offsetY,
Map<String, Integer> iconPictureIndex,
IconMapMarker marker) {
Integer iconIndex = iconPictureIndex.get(marker.getIcon().getName());
if (iconIndex == null) {
try {
iconIndex = ppt.addPicture(new File(getMapIconRoot() + "/" + marker.getIcon().getName() + ".png"),
Picture.PNG);
} catch (IOException e) {
iconIndex = -1;
}
iconPictureIndex.put(marker.getIcon().getName(), iconIndex);
}
if (iconIndex != -1) {
IconRectCalculator rectCtor = new IconRectCalculator(marker.getIcon());
Picture icon = new Picture(iconIndex);
org.activityinfo.legacy.shared.reports.model.Rectangle iconRect = rectCtor.iconRect(offsetX + marker.getX(),
offsetY + marker.getY());
icon.setAnchor(new Rectangle(iconRect.getX(), iconRect.getY(), iconRect.getWidth(), iconRect.getHeight()));
slide.addShape(icon);
}
}
private Dimension computePageSize(MapReportElement element) {
// standard sizes
Dimension[] stdSizes = new Dimension[]{new Dimension(720, 540), // Onscreen Show (4:5)
new Dimension(720, 405), // Onscreen Show (16:9)
new Dimension(780, 540), // A4 Portrait
new Dimension(540, 780)};
for (int i = 0; i != stdSizes.length; ++i) {
if (stdSizes[i].getWidth() > element.getWidth() && stdSizes[i].getHeight() > element.getHeight()) {
return stdSizes[i];
}
}
return new Dimension(element.getWidth(), element.getHeight());
}
}