/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.plugin.print.client.template.impl;
import java.util.ArrayList;
import java.util.List;
import org.geomajas.configuration.FontStyleInfo;
import org.geomajas.configuration.client.ClientMapInfo;
import org.geomajas.configuration.client.ClientRasterLayerInfo;
import org.geomajas.configuration.client.ClientVectorLayerInfo;
import org.geomajas.geometry.Bbox;
import org.geomajas.gwt2.client.GeomajasServerExtension;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.map.ViewPort;
import org.geomajas.gwt2.client.map.layer.Layer;
import org.geomajas.gwt2.client.map.layer.LayersModel;
import org.geomajas.gwt2.client.map.layer.RasterServerLayer;
import org.geomajas.gwt2.client.map.layer.VectorServerLayer;
import org.geomajas.gwt2.plugin.print.client.template.PrintableMapBuilder;
import org.geomajas.gwt2.plugin.print.client.template.TemplateBuilder;
import org.geomajas.gwt2.plugin.print.client.util.PrintLayout;
import org.geomajas.plugin.printing.command.dto.PrintTemplateInfo;
import org.geomajas.plugin.printing.component.dto.ImageComponentInfo;
import org.geomajas.plugin.printing.component.dto.LabelComponentInfo;
import org.geomajas.plugin.printing.component.dto.LayoutConstraintInfo;
import org.geomajas.plugin.printing.component.dto.LegendComponentInfo;
import org.geomajas.plugin.printing.component.dto.LegendGraphicComponentInfo;
import org.geomajas.plugin.printing.component.dto.LegendIconComponentInfo;
import org.geomajas.plugin.printing.component.dto.LegendItemComponentInfo;
import org.geomajas.plugin.printing.component.dto.MapComponentInfo;
import org.geomajas.plugin.printing.component.dto.PageComponentInfo;
import org.geomajas.plugin.printing.component.dto.PrintComponentInfo;
import org.geomajas.plugin.printing.component.dto.RasterizedLayersComponentInfo;
import org.geomajas.plugin.printing.component.dto.ScaleBarComponentInfo;
import org.geomajas.sld.FeatureTypeStyleInfo;
import org.geomajas.sld.RuleInfo;
/**
* Default print template builder, parameters include title, size, raster DPI, orientation, etc...
*
* @author Jan De Moerloose (smartGWT version)
* @author An Buyle (GWT2 version)
*/
public class DefaultTemplateBuilder extends AbstractTemplateBuilder implements TemplateBuilder {
protected double pageWidth;
protected double pageHeight;
protected int marginX;
protected int marginY;
protected String titleText;
protected int rasterDpi;
protected int dpi;
protected boolean withScaleBar;
protected boolean withArrow;
protected MapPresenter mapPresenter;
protected String applicationId;
private PrintableMapBuilder mapBuilder;
public DefaultTemplateBuilder() {
this(new DefaultPrintableMapBuilder());
}
public DefaultTemplateBuilder(PrintableMapBuilder mapBuilder) {
this.mapBuilder = mapBuilder;
}
@Override
public PrintTemplateInfo buildTemplate() {
PrintTemplateInfo template = super.buildTemplate();
template.setId(1L);
template.setName("default");
return template;
}
@Override
protected PageComponentInfo buildPage() {
PageComponentInfo page = super.buildPage();
page.getLayoutConstraint().setWidth((float) pageWidth);
page.getLayoutConstraint().setHeight((float) pageHeight);
page.setBounds(new Bbox(0, 0, pageWidth, pageHeight));
return page;
}
@Override
protected MapComponentInfo buildMap() {
ViewPort viewPort = mapPresenter.getViewPort();
ClientMapInfo mapInfo = mapPresenter.getConfiguration().getHintValue(GeomajasServerExtension.MAPINFO);
double printWidth = getPageWidth() - 2 * marginX;
double printHeight = getPageHeight() - 2 * marginY;
Bbox fittingBox = createFittingBox(viewPort.getBounds(), printWidth / printHeight);
MapComponentInfo map = super.buildMap(fittingBox);
map.getLayoutConstraint().setMarginX(marginX);
map.getLayoutConstraint().setMarginY(marginY);
map.setLocation(new org.geomajas.geometry.Coordinate(fittingBox.getX(), fittingBox.getY()));
map.setPpUnit((float) (printWidth / fittingBox.getWidth()));
map.setTag("map");
map.setMapId(mapInfo.getId());
map.setApplicationId(applicationId);
map.setRasterResolution(rasterDpi);
// use rasterized layers for pure GWT
double rasterScale = map.getPpUnit() * map.getRasterResolution() / 72.0;
// map.getPpUnit() = number of pixels per map unit at 72 dpi
mapBuilder.build(mapPresenter, fittingBox, 1 / rasterScale);
List<PrintComponentInfo> layers = new ArrayList<PrintComponentInfo>();
RasterizedLayersComponentInfo rasterizedLayersComponentInfo = new RasterizedLayersComponentInfo();
rasterizedLayersComponentInfo.setMapInfo(mapInfo);
layers.add(rasterizedLayersComponentInfo);
map.getChildren().addAll(0, layers);
return map;
}
@Override
protected ImageComponentInfo buildArrow() {
if (isWithArrow()) {
ImageComponentInfo northarrow = super.buildArrow();
northarrow.setImagePath("/images/northarrow.gif");
northarrow.getLayoutConstraint().setAlignmentX(LayoutConstraintInfo.RIGHT);
northarrow.getLayoutConstraint().setAlignmentY(LayoutConstraintInfo.TOP);
northarrow.getLayoutConstraint().setMarginX((float) PrintLayout.templateMarginX);
northarrow.getLayoutConstraint().setMarginY((float) PrintLayout.templateMarginY);
northarrow.getLayoutConstraint().setWidth((float) PrintLayout.templateNorthArrowWidth);
northarrow.setTag("arrow");
return northarrow;
} else {
return null;
}
}
@Override
protected LegendComponentInfo buildLegend() {
LegendComponentInfo legend = super.buildLegend();
FontStyleInfo style = new FontStyleInfo();
style.setFamily(PrintLayout.templateDefaultFontFamily);
style.setStyle(PrintLayout.templateDefaultFontStyle);
style.setSize((int) PrintLayout.templateDefaultFontSize);
legend.setFont(style);
ClientMapInfo mapInfo = mapPresenter.getConfiguration().getHintValue(GeomajasServerExtension.MAPINFO);
legend.setMapId(mapInfo.getId());
legend.setTag("legend");
LayersModel layersModel = this.mapPresenter.getLayersModel();
for (int i = 0; i < layersModel.getLayerCount(); i++) {
Layer layer = layersModel.getLayer(i);
if (layer instanceof VectorServerLayer && layer.isShowing()) {
VectorServerLayer vectorLayer = (VectorServerLayer) layer;
ClientVectorLayerInfo layerInfo = (ClientVectorLayerInfo) vectorLayer.getLayerInfo();
FeatureTypeStyleInfo fts = layerInfo.getNamedStyleInfo().getUserStyle().getFeatureTypeStyleList()
.get(0);
for (RuleInfo rule : fts.getRuleList()) {
// use title if present, name if not
String title = (rule.getTitle() != null ? rule.getTitle() : rule.getName());
// fall back to style name
if (title == null) {
title = layerInfo.getNamedStyleInfo().getName();
}
LegendItemComponentInfo item = new LegendItemComponentInfo();
LegendGraphicComponentInfo graphic = new LegendGraphicComponentInfo();
graphic.setLabel(title);
graphic.setRuleInfo(rule);
graphic.setLayerId(layerInfo.getServerLayerId());
item.addChild(graphic);
item.addChild(getLegendLabel(legend, title));
legend.addChild(item);
}
} else if (layer instanceof RasterServerLayer && layer.isShowing()) {
RasterServerLayer rasterLayer = (RasterServerLayer) layer;
ClientRasterLayerInfo layerInfo = rasterLayer.getLayerInfo();
LegendItemComponentInfo item = new LegendItemComponentInfo();
LegendIconComponentInfo icon = new LegendIconComponentInfo();
icon.setLabel(layerInfo.getLabel());
icon.setLayerType(layerInfo.getLayerType());
item.addChild(icon);
item.addChild(getLegendLabel(legend, layerInfo.getLabel()));
legend.addChild(item);
}
}
return legend;
}
@Override
protected LegendComponentInfo buildLegend(Bbox bounds) {
return buildLegend(); // fall-back
}
private LabelComponentInfo getLegendLabel(LegendComponentInfo legend, String text) {
LabelComponentInfo legendLabel = new LabelComponentInfo();
legendLabel.setBackgroundColor(PrintLayout.templateDefaultBackgroundColor);
legendLabel.setBorderColor(PrintLayout.templateDefaultBorderColor);
legendLabel.setFontColor(PrintLayout.templateDefaultColor);
legendLabel.setFont(legend.getFont());
legendLabel.setText(text);
legendLabel.setTextOnly(true);
return legendLabel;
}
@Override
protected ScaleBarComponentInfo buildScaleBar() {
if (isWithScaleBar()) {
ScaleBarComponentInfo bar = super.buildScaleBar();
bar.setTicNumber(3);
bar.setTag("scalebar");
return bar;
} else {
return null;
}
}
@Override
protected LabelComponentInfo buildTitle() {
if (titleText != null) {
LabelComponentInfo title = super.buildTitle();
title.setText(titleText);
title.getLayoutConstraint().setMarginY(2 * marginY);
return title;
} else {
return null;
}
}
public double getPageWidth() {
return pageWidth;
}
public void setPageWidth(double pageWidth) {
this.pageWidth = pageWidth;
}
public double getPageHeight() {
return pageHeight;
}
public void setPageHeight(double pageHeight) {
this.pageHeight = pageHeight;
}
public String getTitleText() {
return titleText;
}
public void setTitleText(String titleText) {
this.titleText = titleText;
}
public int getDpi() {
return dpi;
}
public void setDpi(int dpi) {
this.dpi = dpi;
}
public int getRasterDpi() {
return rasterDpi;
}
public void setRasterDpi(int rasterDpi) {
this.rasterDpi = rasterDpi;
}
public boolean isWithScaleBar() {
return withScaleBar;
}
public void setWithScaleBar(boolean withScaleBar) {
this.withScaleBar = withScaleBar;
}
public boolean isWithArrow() {
return withArrow;
}
public void setWithArrow(boolean withArrow) {
this.withArrow = withArrow;
}
public int getMarginX() {
return marginX;
}
public void setMarginX(int marginX) {
this.marginX = marginX;
}
public int getMarginY() {
return marginY;
}
public void setMarginY(int marginY) {
this.marginY = marginY;
}
public MapPresenter getMapPresenter() {
return mapPresenter;
}
public void setMapPresenter(MapPresenter mapPresenter) {
this.mapPresenter = mapPresenter;
}
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
/**
* Creates the largest possible bounding box that fits around the specified bounding box but has a different
* width/height ratio. and the same centerpoint.
*
* @param bbox
* @param newRatio
* width/height ratio
* @return bbox
*/
public Bbox createFittingBox(Bbox bbox, double newRatio) {
double oldRatio = bbox.getWidth() / bbox.getHeight();
double newWidth = bbox.getWidth();
double newHeight = bbox.getHeight();
if (newRatio < oldRatio) {
// Keep width of bbox , decrease height to fullfill newRatio
newHeight = newWidth / newRatio;
} else {
// Keep height of bbox , decrease width to fullfill newRatio
newWidth = newHeight * newRatio;
}
Bbox result = new Bbox(0, 0, newWidth, newHeight);
result.setX(bbox.getX() + (bbox.getWidth() - newWidth) / 2.0);
result.setY(bbox.getY() + (bbox.getHeight() - newHeight) / 2.0);
return result;
}
}