/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.utils.page; import java.awt.geom.Rectangle2D; import java.math.BigDecimal; import java.util.NoSuchElementException; import java.util.StringTokenizer; import org.simantics.utils.page.MarginUtils; import org.simantics.utils.page.MarginUtils.Margin; import org.simantics.utils.page.MarginUtils.Margins; /** * @see http://www.cl.cam.ac.uk/~mgk25/iso-paper.html for ISO paper dimensions * * TODO: use DataType 0.4 for string serialization of PageDesc */ public class PageDesc { public static int toMillimeters(double points) { return (int) Math.round(points * (25.4/72.)); } public static int toPoints(double millimeters) { return (int) Math.round(millimeters* (72./25.4)); } public static final PageDesc INFINITE = new PageDesc("Infinite", PageOrientation.Portrait, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); public static final PageDesc A0 = new PageDesc("A0", PageOrientation.Portrait, 841, 1189); public static final PageDesc A1 = new PageDesc("A1", PageOrientation.Portrait, 594, 841); public static final PageDesc A2 = new PageDesc("A2", PageOrientation.Portrait, 420, 594); public static final PageDesc A3 = new PageDesc("A3", PageOrientation.Portrait, 297, 420); public static final PageDesc A4 = new PageDesc("A4", PageOrientation.Portrait, 210, 297); public static final PageDesc A5 = new PageDesc("A5", PageOrientation.Portrait, 148, 210); public static final PageDesc A6 = new PageDesc("A6", PageOrientation.Portrait, 105, 148); public static final PageDesc A7 = new PageDesc("A7", PageOrientation.Portrait, 74, 105); public static final PageDesc A8 = new PageDesc("A8", PageOrientation.Portrait, 52, 74); public static final PageDesc A9 = new PageDesc("A9", PageOrientation.Portrait, 37, 52); public static final PageDesc A10 = new PageDesc("A10", PageOrientation.Portrait, 26, 37); public static final PageDesc[] A = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 }; public static final PageDesc[] items = { INFINITE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 }; /** List of PDF usable formats. A sub-set of items. */ public static final PageDesc[] PDF_ITEMS = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 }; public static final PageDesc DEFAULT = A4; private final String text; private final PageOrientation orientation; private final double widthInMM; private final double heightInMM; private final PageCentering centering; private final Margins margins; public static PageDesc[] getPredefinedDescriptions() { return items; } public static PageDesc getByName(String pageDescName) { for (PageDesc item : items) { if ( item.getText().equals( pageDescName ) ) return item; } return null; } public static PageDesc getDescription(String identification) { for (PageDesc pd : getPredefinedDescriptions()) { if (pd.getText().equals(identification)) return pd; } return null; } public static PageDesc getDescription(String identification, PageOrientation o) { for (PageDesc pd : getPredefinedDescriptions()) { if (pd.getText().equals(identification)) return pd.withOrientation(o); } return null; } public static PageDesc getDescription(PageOrientation o, double widthInMM, double heightInMM) { for (PageDesc pd : getPredefinedDescriptions()) { if (pd.widthInMM == widthInMM && pd.heightInMM == heightInMM) return pd.withOrientation(o); } return new PageDesc("Custom", o, widthInMM, heightInMM); } public PageDesc(String text, PageOrientation o, double widthInMM, double heightInMM) { this(text, o, PageCentering.TopLeftAtOrigin, widthInMM, heightInMM); } public String toRepr() { return text + ":" + orientation + ":" + widthInMM + ":" + heightInMM + ":" + margins.top.diagramAbsolute + ":" + margins.bottom.diagramAbsolute + ":" + margins.left.diagramAbsolute + ":" + margins.right.diagramAbsolute; } public static PageDesc fromRepr(String repr) { String[] parts = repr.split(":", 8); return new PageDesc(parts[0], PageOrientation.valueOf(parts[1]), PageCentering.TopLeftAtOrigin, Double.valueOf(parts[2]), Double.valueOf(parts[3]), new Margins( MarginUtils.marginOf(0, 0, Double.valueOf(parts[4])), MarginUtils.marginOf(0, 0, Double.valueOf(parts[5])), MarginUtils.marginOf(0, 0, Double.valueOf(parts[6])), MarginUtils.marginOf(0, 0, Double.valueOf(parts[7])) ) ); } public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM) { this(text, o, c, widthInMM, heightInMM, MarginUtils.NO_MARGINS); } public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM, Margins margins) { if (o == null) throw new IllegalArgumentException("null orientation"); this.text = text; this.orientation = o; this.centering = c; this.widthInMM = widthInMM; this.heightInMM = heightInMM; this.margins = margins; } public boolean isInfinite() { return widthInMM == Double.POSITIVE_INFINITY || heightInMM == Double.POSITIVE_INFINITY; } public String getText() { return text; } public PageOrientation getOrientation() { return orientation; } public PageCentering getCentering() { return centering; } public boolean contains(double x, double y) { if (isInfinite()) return true; if (x < 0 || y < 0) return false; double maxX = getOrientedWidth(); double maxY = getOrientedHeight(); if (x > maxX || y > maxY) return false; return true; } /** * @return */ public double getLeftEdgePos() { if (centering == PageCentering.CenteredAroundOrigin) return -getOrientedWidth() * 0.5; return 0.0; } /** * @return */ public double getTopEdgePos() { if (centering == PageCentering.CenteredAroundOrigin) return -getOrientedHeight() * 0.5; return 0.0; } /** * @return width dimension in millimeters */ public double getWidth() { return widthInMM; } /** * @return height dimension in millimeters */ public double getHeight() { return heightInMM; } /** * @return the margins associated with this page description */ public Margins getMargins() { return margins; } /** * @return width dimension in millimeters with respect to the selected * canvas orientation */ public double getOrientedWidth() { if (orientation == PageOrientation.Portrait) return widthInMM; return heightInMM; } /** * @return height dimension in millimeters with respect to the selected * canvas orientation */ public double getOrientedHeight() { if (orientation == PageOrientation.Portrait) return heightInMM; return widthInMM; } public PageDesc withSizeFrom(PageDesc another) { return new PageDesc(text, orientation, centering, another.widthInMM, another.heightInMM, margins); } public PageDesc withOrientation(PageOrientation o) { if (orientation.equals(o)) { return this; } return new PageDesc(text, o, centering, widthInMM, heightInMM, margins); } public PageDesc withCentering(PageCentering c) { if (centering.equals(c)) { return this; } return new PageDesc(text, orientation, c, widthInMM, heightInMM, margins); } public PageDesc withText(String text) { if (this.text.equals(text)) return this; return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins); } public PageDesc withMargins(Margins margins) { return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins); } public void getPageRectangle(Rectangle2D r) { if (r == null) throw new IllegalArgumentException("null rectangle"); r.setFrame(getLeftEdgePos(), getTopEdgePos(), getOrientedWidth(), getOrientedHeight()); } public void getMarginsRectangle(Rectangle2D r) { if (r == null) throw new IllegalArgumentException("null rectangle"); if (margins == null) getPageRectangle(r); else r.setFrame(getLeftEdgePos()+margins.left.diagramAbsolute, getTopEdgePos()+margins.top.diagramAbsolute, getOrientedWidth()-(margins.left.diagramAbsolute+margins.right.diagramAbsolute), getOrientedHeight()-(margins.top.diagramAbsolute+margins.bottom.diagramAbsolute)); } @Override public int hashCode() { final int PRIME = 31; int result = 1; long temp; temp = Double.doubleToLongBits(heightInMM); result = PRIME * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(widthInMM); result = PRIME * result + (int) (temp ^ (temp >>> 32)); result = PRIME * result + orientation.hashCode(); result = PRIME * result + centering.hashCode(); result = PRIME * result + margins.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final PageDesc other = (PageDesc) obj; if (Double.doubleToLongBits(heightInMM) != Double.doubleToLongBits(other.heightInMM)) return false; if (Double.doubleToLongBits(widthInMM) != Double.doubleToLongBits(other.widthInMM)) return false; if (!orientation.equals(other.orientation)) return false; if (!centering.equals(other.centering)) return false; if (!margins.equals(other.margins)) return false; return true; } @Override public String toString() { return String.format("%s [%s, %s, %s, %s, %s]%s", getClass().getSimpleName(), text, orientation.toString(), widthInMM, heightInMM, centering.toString(), margins); } public static PageDesc deserialize(String desc, PageDesc defaultValue) { if (desc == null) return defaultValue; PageDesc pd = null; try { StringTokenizer tok = new StringTokenizer(desc); String w = tok.nextToken().trim(); String h = tok.nextToken().trim(); String orientation = tok.nextToken().trim(); String centering = tok.nextToken().trim(); String text = tok.nextToken("\u0001").trim(); String margins = tok.nextToken().trim(); double ww = new BigDecimal(w).doubleValue(); double hh = new BigDecimal(h).doubleValue(); PageDesc pd2 = PageDesc.getDescription(PageOrientation.valueOf(orientation), ww, hh); pd2 = pd2.withCentering(PageCentering.valueOf(centering)); pd2 = pd2.withText(text); pd2 = pd2.withMargins(deserializeMargins(margins, MarginUtils.NO_MARGINS)); pd = pd2; } catch (IllegalArgumentException e) { } catch (NoSuchElementException e) { } if (pd == null) pd = defaultValue; return pd; } public static String serialize(PageDesc desc) { //return desc.getText(); return String.format("%s %s %s %s %s\u0001%s", Double.toString(desc.getWidth()), Double.toString(desc.getHeight()), desc.getOrientation().toString(), desc.getCentering().toString(), desc.getText(), serialize(desc.getMargins())); } public static String serialize(Margins margins) { StringBuilder sb = new StringBuilder(); sb.append(serialize(margins.top)); sb.append(";"); sb.append(serialize(margins.bottom)); sb.append(";"); sb.append(serialize(margins.left)); sb.append(";"); sb.append(serialize(margins.right)); return sb.toString(); } private static String serialize(Margin margin) { StringBuilder sb = new StringBuilder(); sb.append(margin.controlRelative); sb.append(" "); sb.append(margin.controlAbsolute); sb.append(" "); sb.append(margin.diagramAbsolute); return sb.toString(); } /** * @param margins * @param defaultValue valid margins * @return */ public static Margins deserializeMargins(String margins, Margins defaultValue) { if (defaultValue == null) throw new NullPointerException("null default value"); String[] split = margins.split(";"); if (split.length != 4) return defaultValue; Margin top = deserializeMargins(split[0], defaultValue.top); Margin bottom = deserializeMargins(split[1], defaultValue.bottom); Margin left = deserializeMargins(split[2], defaultValue.left); Margin right = deserializeMargins(split[3], defaultValue.right); return new Margins(top, bottom, left, right); } /** * @param margin * @param defaultValue a valid margin * @return */ private static Margin deserializeMargins(String margin, Margin defaultValue) { if (defaultValue == null) throw new NullPointerException("null default value"); try { StringTokenizer tok = new StringTokenizer(margin); String cr = tok.nextToken().trim(); String ca = tok.nextToken().trim(); String da = tok.nextToken().trim(); return new Margin(Double.parseDouble(cr), Double.parseDouble(ca), Double.parseDouble(da)); } catch (NumberFormatException e) { return defaultValue; } } }