/******************************************************************************* * Copyright (c) 2004, 2008 John Krasnay and others. * 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: * John Krasnay - initial API and implementation *******************************************************************************/ package net.sf.vex.layout; import net.sf.vex.core.Caret; import net.sf.vex.core.FontMetrics; import net.sf.vex.core.FontResource; import net.sf.vex.core.Graphics; import net.sf.vex.css.Styles; import net.sf.vex.dom.Element; /** * A zero-width box that represents a single offset in the document. */ public class PlaceholderBox extends AbstractBox implements InlineBox { private Element element; private int relOffset; private int textTop; private int baseline; /** * Class constructor. * @param context LayoutContext in effect. * @param element Element containing this placeholder. the element is used * both to determine the size of the box and its caret, but also as a base * point for relOffset. * @param relOffset Offset of the placeholder, relative to the start of * the element. */ public PlaceholderBox(LayoutContext context, Element element, int relOffset) { this.element = element; this.relOffset = relOffset; this.setWidth(0); Graphics g = context.getGraphics(); Styles styles = context.getStyleSheet().getStyles(element); FontResource font = g.createFont(styles.getFont()); FontResource oldFont = g.setFont(font); FontMetrics fm = g.getFontMetrics(); int height = fm.getAscent() + fm.getDescent(); int lineHeight = styles.getLineHeight(); this.textTop = (lineHeight - height) / 2; this.baseline = this.textTop + fm.getAscent(); this.setHeight(lineHeight); g.setFont(oldFont); font.dispose(); } /** * @see net.sf.vex.layout.InlineBox#getBaseline() */ public int getBaseline() { return this.baseline; } /** * @see net.sf.vex.layout.InlineBox#split(net.sf.vex.layout.LayoutContext, int, boolean) */ public Pair split(LayoutContext context, int maxWidth, boolean force) { return new Pair(null, this); } /** * @see net.sf.vex.layout.Box#getCaret(net.sf.vex.layout.LayoutContext, int) */ public Caret getCaret(LayoutContext context, int offset) { return new TextCaret(0, this.textTop, this.baseline - this.textTop); } /** * @see net.sf.vex.layout.Box#getElement() */ public Element getElement() { return this.element; } /** * @see net.sf.vex.layout.Box#getEndOffset() */ public int getEndOffset() { return this.element.getStartOffset() + this.relOffset; } /** * @see net.sf.vex.layout.Box#getStartOffset() */ public int getStartOffset() { return this.element.getStartOffset() + this.relOffset; } /** * @see net.sf.vex.layout.Box#hasContent() */ public boolean hasContent() { return true; } public boolean isEOL() { return false; } /** * @see java.lang.Object#toString() */ public String toString() { return "[placeholder(" + this.getStartOffset() + ")]"; } /** * @see net.sf.vex.layout.Box#viewToModel(net.sf.vex.layout.LayoutContext, int, int) */ public int viewToModel(LayoutContext context, int x, int y) { return this.getStartOffset(); } }