1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.utils.page;
14 import java.awt.geom.Rectangle2D;
15 import java.math.BigDecimal;
16 import java.util.NoSuchElementException;
17 import java.util.StringTokenizer;
19 import org.simantics.utils.page.MarginUtils;
20 import org.simantics.utils.page.MarginUtils.Margin;
21 import org.simantics.utils.page.MarginUtils.Margins;
24 * @see http://www.cl.cam.ac.uk/~mgk25/iso-paper.html for ISO paper dimensions
26 * TODO: use DataType 0.4 for string serialization of PageDesc
28 public class PageDesc {
30 public static int toMillimeters(double points) {
31 return (int) Math.round(points * (25.4/72.));
34 public static int toPoints(double millimeters) {
35 return (int) Math.round(millimeters* (72./25.4));
38 public static final PageDesc INFINITE = new PageDesc("Infinite", PageOrientation.Portrait, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
39 public static final PageDesc A0 = new PageDesc("A0", PageOrientation.Portrait, 841, 1189);
40 public static final PageDesc A1 = new PageDesc("A1", PageOrientation.Portrait, 594, 841);
41 public static final PageDesc A2 = new PageDesc("A2", PageOrientation.Portrait, 420, 594);
42 public static final PageDesc A3 = new PageDesc("A3", PageOrientation.Portrait, 297, 420);
43 public static final PageDesc A4 = new PageDesc("A4", PageOrientation.Portrait, 210, 297);
44 public static final PageDesc A5 = new PageDesc("A5", PageOrientation.Portrait, 148, 210);
45 public static final PageDesc A6 = new PageDesc("A6", PageOrientation.Portrait, 105, 148);
46 public static final PageDesc A7 = new PageDesc("A7", PageOrientation.Portrait, 74, 105);
47 public static final PageDesc A8 = new PageDesc("A8", PageOrientation.Portrait, 52, 74);
48 public static final PageDesc A9 = new PageDesc("A9", PageOrientation.Portrait, 37, 52);
49 public static final PageDesc A10 = new PageDesc("A10", PageOrientation.Portrait, 26, 37);
50 public static final PageDesc[] A = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
51 public static final PageDesc[] items = { INFINITE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
52 /** List of PDF usable formats. A sub-set of items. */
53 public static final PageDesc[] PDF_ITEMS = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
55 public static final PageDesc DEFAULT = A4;
57 private final String text;
59 private final PageOrientation orientation;
61 private final double widthInMM;
63 private final double heightInMM;
65 private final PageCentering centering;
67 private final Margins margins;
70 public static PageDesc[] getPredefinedDescriptions() {
74 public static PageDesc getByName(String pageDescName) {
75 for (PageDesc item : items) {
76 if ( item.getText().equals( pageDescName ) ) return item;
81 public static PageDesc getDescription(String identification) {
82 for (PageDesc pd : getPredefinedDescriptions()) {
83 if (pd.getText().equals(identification))
89 public static PageDesc getDescription(String identification, PageOrientation o) {
90 for (PageDesc pd : getPredefinedDescriptions()) {
91 if (pd.getText().equals(identification))
92 return pd.withOrientation(o);
97 public static PageDesc getDescription(PageOrientation o, double widthInMM, double heightInMM) {
98 for (PageDesc pd : getPredefinedDescriptions()) {
99 if (pd.widthInMM == widthInMM && pd.heightInMM == heightInMM)
100 return pd.withOrientation(o);
102 return new PageDesc("Custom", o, widthInMM, heightInMM);
106 public PageDesc(String text, PageOrientation o, double widthInMM, double heightInMM) {
107 this(text, o, PageCentering.TopLeftAtOrigin, widthInMM, heightInMM);
110 public String toRepr() {
111 return text + ":" + orientation + ":" + widthInMM + ":" + heightInMM
112 + ":" + margins.top.diagramAbsolute
113 + ":" + margins.bottom.diagramAbsolute
114 + ":" + margins.left.diagramAbsolute
115 + ":" + margins.right.diagramAbsolute;
118 public static PageDesc fromRepr(String repr) {
119 String[] parts = repr.split(":", 8);
120 return new PageDesc(parts[0], PageOrientation.valueOf(parts[1]),
121 PageCentering.TopLeftAtOrigin,
122 Double.valueOf(parts[2]), Double.valueOf(parts[3]),
124 MarginUtils.marginOf(0, 0, Double.valueOf(parts[4])),
125 MarginUtils.marginOf(0, 0, Double.valueOf(parts[5])),
126 MarginUtils.marginOf(0, 0, Double.valueOf(parts[6])),
127 MarginUtils.marginOf(0, 0, Double.valueOf(parts[7]))
132 public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM) {
133 this(text, o, c, widthInMM, heightInMM, MarginUtils.NO_MARGINS);
136 public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM, Margins margins) {
138 throw new IllegalArgumentException("null orientation");
141 this.orientation = o;
143 this.widthInMM = widthInMM;
144 this.heightInMM = heightInMM;
145 this.margins = margins;
148 public boolean isInfinite() {
149 return widthInMM == Double.POSITIVE_INFINITY || heightInMM == Double.POSITIVE_INFINITY;
152 public String getText() {
156 public PageOrientation getOrientation() {
160 public PageCentering getCentering() {
164 public boolean contains(double x, double y) {
170 double maxX = getOrientedWidth();
171 double maxY = getOrientedHeight();
172 if (x > maxX || y > maxY)
180 public double getLeftEdgePos() {
181 if (centering == PageCentering.CenteredAroundOrigin)
182 return -getOrientedWidth() * 0.5;
189 public double getTopEdgePos() {
190 if (centering == PageCentering.CenteredAroundOrigin)
191 return -getOrientedHeight() * 0.5;
196 * @return width dimension in millimeters
198 public double getWidth() {
203 * @return height dimension in millimeters
205 public double getHeight() {
210 * @return the margins associated with this page description
212 public Margins getMargins() {
217 * @return width dimension in millimeters with respect to the selected
220 public double getOrientedWidth() {
221 if (orientation == PageOrientation.Portrait)
227 * @return height dimension in millimeters with respect to the selected
230 public double getOrientedHeight() {
231 if (orientation == PageOrientation.Portrait)
236 public PageDesc withSizeFrom(PageDesc another) {
237 return new PageDesc(text, orientation, centering, another.widthInMM, another.heightInMM, margins);
240 public PageDesc withOrientation(PageOrientation o) {
241 if (orientation.equals(o)) {
244 return new PageDesc(text, o, centering, widthInMM, heightInMM, margins);
247 public PageDesc withCentering(PageCentering c) {
248 if (centering.equals(c)) {
251 return new PageDesc(text, orientation, c, widthInMM, heightInMM, margins);
254 public PageDesc withText(String text) {
255 if (this.text.equals(text))
257 return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);
260 public PageDesc withMargins(Margins margins) {
261 return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);
264 public void getPageRectangle(Rectangle2D r) {
266 throw new IllegalArgumentException("null rectangle");
267 r.setFrame(getLeftEdgePos(), getTopEdgePos(), getOrientedWidth(), getOrientedHeight());
270 public void getMarginsRectangle(Rectangle2D r) {
272 throw new IllegalArgumentException("null rectangle");
276 r.setFrame(getLeftEdgePos()+margins.left.diagramAbsolute,
277 getTopEdgePos()+margins.top.diagramAbsolute,
278 getOrientedWidth()-(margins.left.diagramAbsolute+margins.right.diagramAbsolute),
279 getOrientedHeight()-(margins.top.diagramAbsolute+margins.bottom.diagramAbsolute));
283 public int hashCode() {
284 final int PRIME = 31;
287 temp = Double.doubleToLongBits(heightInMM);
288 result = PRIME * result + (int) (temp ^ (temp >>> 32));
289 temp = Double.doubleToLongBits(widthInMM);
290 result = PRIME * result + (int) (temp ^ (temp >>> 32));
291 result = PRIME * result + orientation.hashCode();
292 result = PRIME * result + centering.hashCode();
293 result = PRIME * result + margins.hashCode();
298 public boolean equals(Object obj) {
303 if (getClass() != obj.getClass())
305 final PageDesc other = (PageDesc) obj;
306 if (Double.doubleToLongBits(heightInMM) != Double.doubleToLongBits(other.heightInMM))
308 if (Double.doubleToLongBits(widthInMM) != Double.doubleToLongBits(other.widthInMM))
310 if (!orientation.equals(other.orientation))
312 if (!centering.equals(other.centering))
314 if (!margins.equals(other.margins))
320 public String toString() {
321 return String.format("%s [%s, %s, %s, %s, %s]%s", getClass().getSimpleName(), text, orientation.toString(), widthInMM, heightInMM, centering.toString(), margins);
324 public static PageDesc deserialize(String desc, PageDesc defaultValue) {
330 StringTokenizer tok = new StringTokenizer(desc);
331 String w = tok.nextToken().trim();
332 String h = tok.nextToken().trim();
333 String orientation = tok.nextToken().trim();
334 String centering = tok.nextToken().trim();
335 String text = tok.nextToken("\u0001").trim();
336 String margins = tok.nextToken().trim();
338 double ww = new BigDecimal(w).doubleValue();
339 double hh = new BigDecimal(h).doubleValue();
341 PageDesc pd2 = PageDesc.getDescription(PageOrientation.valueOf(orientation), ww, hh);
342 pd2 = pd2.withCentering(PageCentering.valueOf(centering));
343 pd2 = pd2.withText(text);
344 pd2 = pd2.withMargins(deserializeMargins(margins, MarginUtils.NO_MARGINS));
347 } catch (IllegalArgumentException e) {
348 } catch (NoSuchElementException e) {
355 public static String serialize(PageDesc desc) {
356 //return desc.getText();
357 return String.format("%s %s %s %s %s\u0001%s",
358 Double.toString(desc.getWidth()),
359 Double.toString(desc.getHeight()),
360 desc.getOrientation().toString(),
361 desc.getCentering().toString(),
363 serialize(desc.getMargins()));
366 public static String serialize(Margins margins) {
367 StringBuilder sb = new StringBuilder();
368 sb.append(serialize(margins.top));
370 sb.append(serialize(margins.bottom));
372 sb.append(serialize(margins.left));
374 sb.append(serialize(margins.right));
375 return sb.toString();
378 private static String serialize(Margin margin) {
379 StringBuilder sb = new StringBuilder();
380 sb.append(margin.controlRelative);
382 sb.append(margin.controlAbsolute);
384 sb.append(margin.diagramAbsolute);
385 return sb.toString();
390 * @param defaultValue valid margins
393 public static Margins deserializeMargins(String margins, Margins defaultValue) {
394 if (defaultValue == null)
395 throw new NullPointerException("null default value");
397 String[] split = margins.split(";");
398 if (split.length != 4)
401 Margin top = deserializeMargins(split[0], defaultValue.top);
402 Margin bottom = deserializeMargins(split[1], defaultValue.bottom);
403 Margin left = deserializeMargins(split[2], defaultValue.left);
404 Margin right = deserializeMargins(split[3], defaultValue.right);
405 return new Margins(top, bottom, left, right);
410 * @param defaultValue a valid margin
413 private static Margin deserializeMargins(String margin, Margin defaultValue) {
414 if (defaultValue == null)
415 throw new NullPointerException("null default value");
418 StringTokenizer tok = new StringTokenizer(margin);
419 String cr = tok.nextToken().trim();
420 String ca = tok.nextToken().trim();
421 String da = tok.nextToken().trim();
422 return new Margin(Double.parseDouble(cr), Double.parseDouble(ca), Double.parseDouble(da));
423 } catch (NumberFormatException e) {