/******************************************************************************* * Copyright (c) 2012 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: * Semantum Oy - initial API and implementation *******************************************************************************/ package org.simantics.diagram.elements; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; /** * Auxiliary class for drawing positioned and single lines of laid out text. * * @author Tuukka Lehtonen * * @see TextNode * @see TextLayout */ class Line { public interface BoundsProcedure { Rectangle2D getBounds(Line line); } public static BoundsProcedure BBOX = new BoundsProcedure() { @Override public Rectangle2D getBounds(Line line) { return line.bbox; } }; public static BoundsProcedure ABBOX = new BoundsProcedure() { @Override public Rectangle2D getBounds(Line line) { return line.abbox; } }; public final String document; public final int startOffset; public final int endOffset; float drawPosX; float drawPosY; float alignedPosX; float alignedPosY; TextLayout layout; Rectangle2D bbox; Rectangle2D abbox; public Line(String document, int startOffset, int endOffset) { int len = document.length(); if (endOffset < startOffset) throw new IllegalArgumentException("endOffset (" + endOffset + ") < startOffset (" + startOffset + ")"); if (startOffset < 0 || startOffset > len) throw new IllegalArgumentException("startOffset " + startOffset + " out of bounds [0," + len + "]"); if (endOffset < 0 || endOffset > len) throw new IllegalArgumentException("endOffset " + endOffset + " out of bounds [0," + len + "]"); this.document = document; this.startOffset = startOffset; this.endOffset = endOffset; } public void render(Graphics2D g) { if (layout != null) layout.draw(g, alignedPosX, alignedPosY); } public String getText() { return document.substring(startOffset, endOffset); } public boolean intersectsRange(int start, int end) { return start < endOffset && end > startOffset; } public boolean containsRange(int start, int end) { return start >= startOffset && start <= endOffset && end > startOffset && end <= endOffset; } public boolean containsOffset(int caret) { return startOffset <= caret && caret <= endOffset; } public Shape getLogicalHighlightShape(int start, int end) { return layout.getLogicalHighlightShape( Math.max(0, start - startOffset), Math.min(endOffset - startOffset, end - startOffset)); } public Shape[] getCaretShapes(int caret) { return layout.getCaretShapes(caret - startOffset); } public void translate(Graphics2D g, float xOffset, float yOffset) { g.translate(alignedPosX + xOffset, alignedPosY + yOffset); } public void translateInv(Graphics2D g, float xOffset, float yOffset) { g.translate(-alignedPosX - xOffset, - alignedPosY - yOffset); } public void alignOffset(double x, double y) { alignedPosX = drawPosX + (float) x; alignedPosY = drawPosY + (float) y; if (abbox == null) abbox = new Rectangle2D.Float(); abbox.setFrame(bbox.getX() + x, bbox.getY() + y, bbox.getWidth(), bbox.getHeight()); //System.out.println("offset(" + x + ", " + y + "): " + this); } @Override public String toString() { return getClass().getSimpleName() + "[startOffset=" + startOffset + ", endOffset=" + endOffset + ", x=" + drawPosX + ", y=" + drawPosY + ", ax='" + alignedPosX + ", ay=" + alignedPosY + ", text='" + getText() + ", bbox='" + bbox + ", abbox=" + abbox + "']"; } }