Package org.geomajas.plugin.printing.component.impl

Source Code of org.geomajas.plugin.printing.component.impl.ScaleBarComponentImpl

/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 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.plugin.printing.component.impl;

import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;

import org.geomajas.configuration.client.ClientMapInfo;
import org.geomajas.geometry.Crs;
import org.geomajas.plugin.printing.component.LayoutConstraint;
import org.geomajas.plugin.printing.component.PdfContext;
import org.geomajas.plugin.printing.component.PrintComponentVisitor;
import org.geomajas.plugin.printing.component.ScaleBarComponent;
import org.geomajas.plugin.printing.component.dto.ScaleBarComponentInfo;
import org.geomajas.plugin.printing.component.service.PrintConfigurationService;
import org.geomajas.plugin.printing.component.service.PrintDtoConverterService;
import org.geomajas.plugin.printing.parser.FontConverter;
import org.geomajas.service.GeoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.lowagie.text.Rectangle;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

/**
* Scale bar component for inclusion in printed documents.
*
* @author Jan De Moerloose
*/
@Component()
@Scope(value = "prototype")
public class ScaleBarComponentImpl extends AbstractPrintComponent<ScaleBarComponentInfo> implements ScaleBarComponent {

  @XStreamOmitField
  private final Logger log = LoggerFactory.getLogger(ScaleBarComponentImpl.class);

  /**
   * The unit (meter, mile, degree)
   */
  private String unit = "units";

  /**
   * The number of tics for the scalebar
   */
  private int ticNumber;

  /**
   * The labels on top of the ticks
   */
  private List<String> tickLabels = new ArrayList<String>();

  /**
   * The calculated sizes of the ticks
   */
  private List<Rectangle> tickSizes = new ArrayList<Rectangle>();

  /**
   * The label font
   */
  @XStreamConverter(FontConverter.class)
  private Font font = new Font("Dialog", Font.PLAIN, 12);

  /**
   * Width a tic (double checkerboard style).
   */
  private float ticWidth;

  /**
   * Height of a tic (double checkerboard style).
   */
  private float ticHeight;

  @Autowired
  @XStreamOmitField
  private PrintConfigurationService configurationService;
 
  @Autowired
  @XStreamOmitField
  private GeoService geoService;

  @Autowired
  @XStreamOmitField
  private PrintDtoConverterService converterService;

  private static final float[] ALLOW_TICK_NUMBERS = new float[] { 1, 2, 5, 10, 25, 50, 100, 200, 250, 500, 750 };

  private static final String[] UNIT_PREFIXES = new String[] { "n", "m", "", "k", "M" };

  public ScaleBarComponentImpl() {
    getConstraint().setAlignmentX(LayoutConstraint.LEFT);
    getConstraint().setAlignmentY(LayoutConstraint.BOTTOM);
    getConstraint().setMarginX(20);
    getConstraint().setMarginY(20);
    getConstraint().setWidth(200);
 
 
  public Font getFont() {
    return font;
  }

  public void setFont(Font font) {
    this.font = font;
  }

  /**
   * Call back visitor.
   *
   * @param visitor visitor
   */
  public void accept(PrintComponentVisitor visitor) {
    visitor.visit(this);
  }

  @Override
  public void calculateSize(PdfContext context) {
    // clear labels and sizes to make this method idempotent
    tickLabels.clear();
    tickSizes.clear();
   
    // the width must be set !!
    float width = getConstraint().getWidth();

    // Calculate width in map units and round.
    float widthInUnits = width / getMap().getPpUnit();

    // Calculate ideal tic width in units
    float ticWidthInUnits = widthInUnits / getTicNumber();

    // Calculate minimal tic width in units
    int ticLog = (int) Math.floor(Math.log10(ticWidthInUnits) / 3);
    float minTicWidthInUnits = (float) Math.pow(10, ticLog * 3);

    // Find the highest nice number
    float nicestNumber = 0;
    for (float allowTickNumber : ALLOW_TICK_NUMBERS) {
      if (minTicWidthInUnits * allowTickNumber > ticWidthInUnits) {
        break;
      } else {
        nicestNumber = allowTickNumber;
      }
    }
    ticWidthInUnits = minTicWidthInUnits * nicestNumber;
    ticWidth = ticWidthInUnits * getMap().getPpUnit();
    ticHeight = ticWidth * 0.3f;
    int ticCount = getTicNumber();

    // Calculate the labels
    ClientMapInfo map = configurationService.getMapInfo(getMap().getMapId(), getMap().getApplicationId());
    if (map != null) {
      log.debug("calculateSize getMap.getId({}), res {}", getMap().getId(), map);
      Crs crs;
      try {
        crs = geoService.getCrs2(map.getCrs());
        unit = crs.getCoordinateSystem().getAxis(0).getUnit().toString();
      } catch (Exception e) {
        log.error("could not calculate map unit", e);
      }
    }
//    font = new Font("Dialog", Font.PLAIN, (int) (0.8 * ticHeight));
    for (int i = 0; i <= ticCount; i++) {
      String label = "" + (int) (i * ticWidthInUnits / Math.pow(10, 3 * ticLog));
      String units = ((ticLog >= -2 && ticLog <= 2) ? UNIT_PREFIXES[ticLog + 2] : "*10^" + (ticLog * 3)) + unit;
      if (i == ticCount) {
        label += " " + units;
      }
      tickLabels.add(label);
      tickSizes.add(context.getTextSize(label, font));
    }

    // Calculate size
    width = ticWidth * ticCount;
    Rectangle first = context.getTextSize(tickLabels.get(0), font);
    Rectangle last = context.getTextSize(tickLabels.get(ticCount), font);
    width += 0.5 * first.getWidth();
    width += 0.5 * last.getWidth();
    float height = ticHeight;
    height += first.getHeight();
    setBounds(new Rectangle(0, 0, width, height));
  }

  @Override
  public void render(PdfContext context) {
    // draw the tics
    float lowX = 0.5f * tickSizes.get(0).getWidth();
    float lowY = 0;
    float highX = lowX;
    float highY = 0.333f * ticHeight;
    Rectangle baseRect = new Rectangle(0, 0, ticWidth, 0.333f * ticHeight);

    // fills
    for (int i = 0; i < ticNumber; i++) {
      if (i % 2 == 0) {
        context.moveRectangleTo(baseRect, lowX, lowY);
        context.fillRectangle(baseRect, Color.white);
        context.strokeRectangle(baseRect, Color.black, 0.5f);
        context.moveRectangleTo(baseRect, highX, highY);
        context.fillRectangle(baseRect, Color.black);
        context.strokeRectangle(baseRect, Color.black, 0.5f);
      } else {
        context.moveRectangleTo(baseRect, highX, highY);
        context.fillRectangle(baseRect, Color.white);
        context.strokeRectangle(baseRect, Color.black, 0.5f);
        context.moveRectangleTo(baseRect, lowX, lowY);
        context.fillRectangle(baseRect, Color.black);
        context.strokeRectangle(baseRect, Color.black, 0.5f);
      }
      lowX += ticWidth;
      highX += ticWidth;
    }

    // tick extensions
    highX = 0.5f * tickSizes.get(0).getWidth();
    highY = 0.6666f * ticHeight;
    for (int i = 0; i <= ticNumber; i++) {
      context.drawRelativePath(new float[] { 0, 0 }, new float[] { 0, 1 }, new Rectangle(highX, highY, highX,
          0.75f * ticHeight), Color.black, 0.5f, null);
      highX += ticWidth;
    }

    // position and print the labels
    float labelX = 0.5f * tickSizes.get(0).getWidth();
    float labelY = ticHeight;
    for (int i = 0; i < tickLabels.size(); i++) {
      Rectangle box = tickSizes.get(i);
      // center the label
      context.moveRectangleTo(box, labelX - 0.5f * box.getWidth(), labelY);
      context.drawText(tickLabels.get(i), font, box, Color.black);
      labelX += ticWidth;
    }
  }

  MapComponentImpl getMap() {
    return (MapComponentImpl) getParent();
  }

  /* (non-Javadoc)
   * @see org.geomajas.plugin.printing.component.impl.ScaleBarComponent#getTicNumber()
   */
  public int getTicNumber() {
    return ticNumber;
  }

  public void setTicNumber(int ticNumber) {
    this.ticNumber = ticNumber;
  }

  /* (non-Javadoc)
   * @see org.geomajas.plugin.printing.component.impl.ScaleBarComponent#getUnit()
   */
  public String getUnit() {
    return unit;
  }

  public void setUnit(String unit) {
    this.unit = unit;
  }
 
  public void fromDto(ScaleBarComponentInfo scaleBarInfo) {
    super.fromDto(scaleBarInfo);
    setTicNumber(scaleBarInfo.getTicNumber());
    setUnit(scaleBarInfo.getUnit());
    setFont(converterService.toInternal(scaleBarInfo.getFont()));
  }

 
}
TOP

Related Classes of org.geomajas.plugin.printing.component.impl.ScaleBarComponentImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.