org.mapfish.print.scalebar.ScalebarDrawer.java Source code

Java tutorial

Introduction

Here is the source code for org.mapfish.print.scalebar.ScalebarDrawer.java

Source

/*
 * Copyright (C) 2009  Camptocamp
 *
 * This file is part of MapFish Server
 *
 * MapFish Server is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MapFish Server 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with MapFish Server.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mapfish.print.scalebar;

import com.lowagie.text.Font;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import org.mapfish.print.ChunkDrawer;
import org.mapfish.print.PDFCustomBlocks;
import org.mapfish.print.config.layout.ScalebarBlock;

import java.awt.geom.AffineTransform;
import java.util.List;

/**
 * Base class for drawing a scale bar.
 */
public abstract class ScalebarDrawer extends ChunkDrawer {
    protected final ScalebarBlock block;
    protected final List<Label> labels;
    protected final int barSize;
    private final int labelDistance;
    protected final int subIntervals;
    protected final float intervalWidth;
    private final Font pdfFont;
    private final float leftLabelMargin;
    private final float rightLabelMargin;
    private final float maxLabelWidth;
    private final float maxLabelHeight;

    public ScalebarDrawer(PDFCustomBlocks customBlocks, ScalebarBlock block, List<Label> labels, int barSize,
            int labelDistance, int subIntervals, float intervalWidth, Font pdfFont, float leftLabelMargin,
            float rightLabelMargin, float maxLabelWidth, float maxLabelHeight) {
        super(customBlocks);
        this.block = block;
        this.labels = labels;
        this.barSize = barSize;
        this.labelDistance = labelDistance;
        this.subIntervals = subIntervals;
        this.intervalWidth = intervalWidth;
        this.pdfFont = pdfFont;
        this.leftLabelMargin = leftLabelMargin;
        this.rightLabelMargin = rightLabelMargin;
        this.maxLabelWidth = maxLabelWidth;
        this.maxLabelHeight = maxLabelHeight;
    }

    public static ScalebarDrawer create(PDFCustomBlocks customBlocks, ScalebarBlock block, Type type,
            List<Label> labels, int barSize, int labelDistance, int subIntervals, float intervalWidth, Font pdfFont,
            float leftLabelMargin, float rightLabelMargin, float maxLabelWidth, float maxLabelHeight) {
        switch (type) {
        case BAR:
            return new BarScalebarDrawer(customBlocks, block, labels, barSize, labelDistance, subIntervals,
                    intervalWidth, pdfFont, leftLabelMargin, rightLabelMargin, maxLabelWidth, maxLabelHeight);
        case BAR_SUB:
            return new BarSubScalebarDrawer(customBlocks, block, labels, barSize, labelDistance, subIntervals,
                    intervalWidth, pdfFont, leftLabelMargin, rightLabelMargin, maxLabelWidth, maxLabelHeight);
        case LINE:
            return new LineScalebarDrawer(customBlocks, block, labels, barSize, labelDistance, subIntervals,
                    intervalWidth, pdfFont, leftLabelMargin, rightLabelMargin, maxLabelWidth, maxLabelHeight);
        default:
            throw new RuntimeException("Unknown type: " + type);
        }
    }

    public void renderImpl(Rectangle rectangle, PdfContentByte dc) {
        dc.saveState();
        try {
            //sets the transformation for drawing the labels and do it
            final AffineTransform rotate = getRotationTransform(block.getBarDirection());
            final AffineTransform labelTransform = AffineTransform.getTranslateInstance(rectangle.getLeft(),
                    rectangle.getBottom());
            labelTransform.concatenate(rotate);
            labelTransform.translate(leftLabelMargin, maxLabelHeight);
            dc.transform(labelTransform);
            dc.setColorStroke(block.getColorVal());
            dc.setFontAndSize(pdfFont.getCalculatedBaseFont(false), pdfFont.getSize());
            drawLabels(dc);

            dc.restoreState();
            dc.saveState();

            //sets the transformation for drawing the bar and do it
            final AffineTransform lineTransform = AffineTransform.getTranslateInstance(rectangle.getLeft(),
                    rectangle.getBottom());
            lineTransform.concatenate(rotate);
            lineTransform.translate(leftLabelMargin, labelDistance + maxLabelHeight);
            dc.transform(lineTransform);
            dc.setLineWidth((float) block.getLineWidth());
            dc.setColorStroke(block.getColorVal());
            drawBar(dc);
        } finally {
            dc.restoreState();
        }
    }

    private AffineTransform getRotationTransform(Direction direction) {
        AffineTransform rotate;
        switch (direction) {
        case UP:
            rotate = new AffineTransform(1, 0, 0, 1, 0, 0);
            break;
        case DOWN:
            rotate = new AffineTransform(-1, 0, 0, -1, getTotalWidth(), getTotalHeight());
            break;
        case LEFT:
            rotate = new AffineTransform(0, 1, -1, 0, getTotalHeight(), 0);
            break;
        case RIGHT:
            rotate = new AffineTransform(0, -1, 1, 0, 0, getTotalWidth());
            break;
        default:
            throw new RuntimeException("Unknown orientation: " + direction);
        }
        return rotate;
    }

    private float getTotalWidth() {
        return intervalWidth * block.getIntervals() + leftLabelMargin + rightLabelMargin;
    }

    private float getTotalHeight() {
        return barSize + labelDistance + maxLabelHeight;
    }

    /**
     * Draws the labels. The transformation is setup in a manner where the
     * position of the labels is at (label.paperOffset,0).
     */
    private void drawLabels(PdfContentByte dc) {
        float prevPos = getTotalWidth();

        for (int i = labels.size() - 1; i >= 0; --i) {
            Label label = labels.get(i);
            final float offsetH;
            final float offsetV;
            if (block.getTextDirection().getAngle() == block.getBarDirection().getAngle()) {
                //same direction
                offsetH = -label.width / 2;
                offsetV = -maxLabelHeight;

            } else if (block.getTextDirection().getAngle() == -block.getBarDirection().getAngle()) {
                //opposite direction
                offsetH = label.width / 2;
                offsetV = 0;
            } else if (block.getTextDirection().getAngle() - block.getBarDirection().getAngle() < 0) {
                offsetH = label.width / 2;
                offsetV = -label.height;
            } else {
                offsetH = -label.width / 2;
                offsetV = 0;
            }

            if (label.paperOffset + Math.abs(offsetH) <= prevPos - 1) {
                dc.beginText();
                dc.showTextAligned(PdfContentByte.ALIGN_LEFT, label.label, label.paperOffset + offsetH, offsetV,
                        (float) (block.getBarDirection().getAngle() - block.getTextDirection().getAngle()));
                dc.endText();
                prevPos = label.paperOffset - Math.abs(offsetH);
            } else {
                //the label would be written over the previous one => ignore it
                label.label = null;
            }
        }
    }

    /**
     * Draws the bar itself. The transformation is setup in a manner where the
     * bar starts at (0,0) and ends at (intervals*intervalWidth, lineWidth)
     */
    protected abstract void drawBar(PdfContentByte dc);

}