/* * Copyright (c) 2007 Matthew Hall 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: * Matthew Hall - initial API and implementation */ package org.eclipse.nebula.paperclips.core.text; import org.eclipse.nebula.paperclips.core.Print; import org.eclipse.nebula.paperclips.core.PrintIterator; import org.eclipse.nebula.paperclips.core.PrintPiece; import org.eclipse.nebula.paperclips.core.internal.piece.EmptyPiece; import org.eclipse.nebula.paperclips.core.internal.util.ResourcePool; import org.eclipse.nebula.paperclips.core.internal.util.Util; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; /** * A class for adding line breaks corresponding to a particular font size. * Currently this class is used internally by StyledTextPrint to implement the * newline() feature. * * @author Matthew Hall */ public class LineBreakPrint implements Print { final FontData font; /** * Constructs a new LineBreakPrint on the given font. * * @param font * the font which determines the height of the line break. */ public LineBreakPrint(FontData font) { Util.notNull(font); this.font = font; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((font == null) ? 0 : font.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; LineBreakPrint other = (LineBreakPrint) obj; if (font == null) { if (other.font != null) return false; } else if (!font.equals(other.font)) return false; return true; } public PrintIterator iterator(Device device, GC gc) { return new LineBreakIterator(this, device, gc); } } class LineBreakIterator implements PrintIterator { private static final int MIN_HEIGHT = 0; private static final int MIN_WIDTH = 1; private final int lineHeight; private boolean hasNext = true; LineBreakIterator(LineBreakPrint print, Device device, GC gc) { this(calculateLineHeight(print, device, gc)); } private LineBreakIterator(int lineHeight) { this.lineHeight = lineHeight; } private static int calculateLineHeight(LineBreakPrint print, Device device, GC gc) { Font oldFont = gc.getFont(); gc.setFont(ResourcePool.forDevice(device).getFont(print.font)); int result = gc.getFontMetrics().getHeight(); gc.setFont(oldFont); return result; } public Point minimumSize() { return new Point(MIN_WIDTH, MIN_HEIGHT); } public Point preferredSize() { return new Point(MIN_WIDTH, lineHeight); } public boolean hasNext() { return hasNext; } public PrintPiece next(int width, int height) { if (width < MIN_WIDTH || height < MIN_HEIGHT) return null; hasNext = false; return new EmptyPiece(new Point(width, Math.min(height, lineHeight))); } public PrintIterator copy() { return hasNext ? new LineBreakIterator(lineHeight) : this; } }