/*
* Copyright (c) 2005 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.page;
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.util.PaperClipsUtil;
import org.eclipse.nebula.paperclips.core.internal.util.ResourcePool;
import org.eclipse.nebula.paperclips.core.internal.util.Util;
import org.eclipse.nebula.paperclips.core.text.TextStyle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
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;
import org.eclipse.swt.graphics.RGB;
/**
* Displays the page number and page count within the context of a
* {@link PagePrint}. To properly display page numbers, instances of this class
* should be created using the {@link PageNumber} argument which is passed to
* the {@link PageDecoration#createPrint(PageNumber)} method by PagePrint.
* <p>
* PageNumberPrints are never greedy with layout space, even with center- or
* right-alignment. (Greedy prints take up all the available space on the page.)
* Therefore, when center- or right-alignment is required, it is necessary to
* wrap the page number in a Print which will enforce the same alignment.
* Usually this is a center:default:grow or right:default:grow column in a
* GridPrint.
*
* @author Matthew Hall
* @see PagePrint
* @see PageDecoration
* @see PageNumber
* @see PageNumberFormat
* @see DefaultPageNumberFormat
*/
public class PageNumberPrint implements Print {
/** The default font data for a PageNumberPrint. Value is device-dependent. */
public static final FontData DEFAULT_FONT_DATA = new FontData();
/** The default alignment for a PageNumberPrint. Value is SWT.LEFT. */
public static final int DEFAULT_ALIGN = SWT.LEFT;
/** The default text style. Value is device-dependent. */
public static final TextStyle DEFAULT_TEXT_STYLE = new TextStyle().font(
DEFAULT_FONT_DATA).align(DEFAULT_ALIGN);
PageNumber pageNumber;
TextStyle textStyle;
PageNumberFormat format;
/**
* Constructs a PageNumberPrint for the given page number.
*
* @param pageNumber
* the page number of the page this Print will appear on.
*/
public PageNumberPrint(PageNumber pageNumber) {
this(pageNumber, DEFAULT_TEXT_STYLE);
}
/**
* Constructs a PageNumberPrint for the given page number and font.
*
* @param pageNumber
* the page number of the page this Print will appear on.
* @param fontData
* the font that this Print will appear in.
*/
public PageNumberPrint(PageNumber pageNumber, FontData fontData) {
this(pageNumber, DEFAULT_TEXT_STYLE.font(fontData));
}
/**
* Constructs a PageNumberPrint for the given page number and alignment.
*
* @param pageNumber
* the page number of the page this Print will appear on.
* @param align
* the horizontal alignment of the text.
*/
public PageNumberPrint(PageNumber pageNumber, int align) {
this(pageNumber, DEFAULT_TEXT_STYLE.align(align));
}
/**
* Constructs a PageNumberPrint for the given page number, font and
* alignment.
*
* @param pageNumber
* the page number of the page this Print will appear on.
* @param fontData
* the font that this Print will appear in.
* @param align
* the horizontal alignment of the text.
*/
public PageNumberPrint(PageNumber pageNumber, FontData fontData, int align) {
this(pageNumber, DEFAULT_TEXT_STYLE.font(fontData).align(align));
}
/**
* Constructs a PageNumberPrint for the given page number and text style.
*
* @param pageNumber
* the page number of the page this Print will appear on.
* @param textStyle
* the text style that this Print will appear in.
*/
public PageNumberPrint(PageNumber pageNumber, TextStyle textStyle) {
setPageNumber(pageNumber);
setTextStyle(textStyle);
setPageNumberFormat(new DefaultPageNumberFormat());
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((pageNumber == null) ? 0 : pageNumber.hashCode());
result = prime * result
+ ((textStyle == null) ? 0 : textStyle.hashCode());
result = prime * result + ((format == null) ? 0 : format.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PageNumberPrint other = (PageNumberPrint) obj;
if (pageNumber == null) {
if (other.pageNumber != null)
return false;
} else if (!pageNumber.equals(other.pageNumber))
return false;
if (textStyle == null) {
if (other.textStyle != null)
return false;
} else if (!textStyle.equals(other.textStyle))
return false;
if (format == null) {
if (other.format != null)
return false;
} else if (!format.equals(other.format))
return false;
return true;
}
/**
* Sets the page number to the argument.
*
* @param pageNumber
* the new page number.
*/
public void setPageNumber(PageNumber pageNumber) {
Util.notNull(pageNumber);
this.pageNumber = pageNumber;
}
/**
* Returns the page number of this Print.
*
* @return the page number of this Print.
*/
public PageNumber getPageNumber() {
return pageNumber;
}
/**
* Sets the text font to the argument.
*
* @param fontData
* the new text font.
*/
public void setFontData(FontData fontData) {
Util.notNull(fontData);
setTextStyle(textStyle.font(fontData));
}
/**
* Returns the text font.
*
* @return the text font.
*/
public FontData getFontData() {
return textStyle.getFontData();
}
/**
* Sets the horizontal text alignment to the argument.
*
* @param align
* the horizontal alignment. Must be one of {@link SWT#LEFT },
* {@link SWT#CENTER } or {@link SWT#RIGHT }.
*/
public void setAlign(int align) {
setTextStyle(textStyle.align(checkAlign(align)));
}
/**
* Returns the horizontal text alignment.
*
* @return the horizontal text alignment.
*/
public int getAlign() {
return textStyle.getAlignment();
}
private int checkAlign(int align) {
return PaperClipsUtil.firstMatch(align, new int[] { SWT.LEFT,
SWT.CENTER, SWT.RIGHT }, SWT.LEFT);
}
/**
* Returns the text style that will be used to render the page number
*
* @return the text style that will be used to render the page number
*/
public TextStyle getTextStyle() {
return textStyle;
}
/**
* Sets the text style that will be used to render the page number
*
* @param textStyle
* the text style
*/
public void setTextStyle(TextStyle textStyle) {
Util.notNull(textStyle);
this.textStyle = textStyle;
}
/**
* Sets the format that will be used to convert the page number to a text
* string.
*
* @param format
* the new page number format.
*/
public void setPageNumberFormat(PageNumberFormat format) {
Util.notNull(format);
this.format = format;
}
/**
* Returns the page number format. This property determines how the
* PageNumber will be converted into a String representing the page number.
* The default value of this property formats page numbers as follows:<br>
*
* <pre>
* Page 1 of 5
* </pre>
*
* @return the page number format.
*/
public PageNumberFormat getPageNumberFormat() {
return format;
}
/**
* Sets the text color.
*
* @param foreground
* the new text color.
*/
public void setRGB(RGB foreground) {
Util.notNull(foreground);
setTextStyle(textStyle.foreground(foreground));
}
/**
* Returns the text color.
*
* @return the text color.
*/
public RGB getRGB() {
return textStyle.getForeground();
}
public PrintIterator iterator(Device device, GC gc) {
return new PageNumberIterator(this, device, gc);
}
}
class PageNumberIterator implements PrintIterator {
private final Device device;
private final GC gc;
final PageNumber pageNumber;
final TextStyle textStyle;
final PageNumberFormat format;
final Point size;
boolean hasNext = true;
PageNumberIterator(PageNumberPrint print, Device device, GC gc) {
this.device = device;
this.gc = gc;
this.pageNumber = print.pageNumber;
this.textStyle = print.textStyle;
this.format = print.format;
// Calculate the size for the largest possible page number string.
Font oldFont = gc.getFont();
try {
gc.setFont(ResourcePool.forDevice(device).getFont(
textStyle.getFontData()));
size = gc.textExtent(format.format(new PageNumber() {
public int getPageCount() {
return 9999;
}
public int getPageNumber() {
return 9998;
} // (zero-based index)
}));
} finally {
gc.setFont(oldFont);
}
}
PageNumberIterator(PageNumberIterator that) {
this.device = that.device;
this.gc = that.gc;
this.pageNumber = that.pageNumber;
this.textStyle = that.textStyle;
this.format = that.format;
this.size = that.size;
this.hasNext = that.hasNext;
}
public boolean hasNext() {
return hasNext;
}
public Point minimumSize() {
return size;
}
public Point preferredSize() {
return size;
}
public PrintPiece next(int width, int height) {
if (width < size.x || height < size.y)
return null;
Point size = new Point(this.size.x, this.size.y);
int align = textStyle.getAlignment();
if (align == SWT.CENTER || align == SWT.RIGHT)
size.x = width;
PageNumberPiece piece = new PageNumberPiece(this, device, size);
hasNext = false;
return piece;
}
public PrintIterator copy() {
return new PageNumberIterator(this);
}
}
class PageNumberPiece implements PrintPiece {
private final Device device;
private final Point size;
private final PageNumber pageNumber;
private final TextStyle textStyle;
private final PageNumberFormat format;
PageNumberPiece(PageNumberIterator iter, Device device, Point size) {
this.device = device;
this.size = size;
this.pageNumber = iter.pageNumber;
this.textStyle = iter.textStyle;
this.format = iter.format;
}
public Point getSize() {
return new Point(size.x, size.y);
}
public void paint(final GC gc, final int x, final int y) {
Font oldFont = gc.getFont();
Color oldForeground = gc.getForeground();
Point size = getSize();
try {
ResourcePool resources = ResourcePool.forDevice(device);
gc.setFont(resources.getFont(textStyle.getFontData()));
gc.setForeground(resources.getColor(textStyle.getForeground()));
String text = format.format(pageNumber);
gc.drawText(text, x
+ getHorzAlignmentOffset(gc.textExtent(text).x, size.x), y,
true);
} finally {
gc.setFont(oldFont);
gc.setForeground(oldForeground);
}
}
private int getHorzAlignmentOffset(int textWidth, int totalWidth) {
int offset = 0;
switch (textStyle.getAlignment()) {
case SWT.CENTER:
offset = (totalWidth - textWidth) / 2;
break;
case SWT.RIGHT:
offset = totalWidth - textWidth;
break;
}
return offset;
}
public void dispose() {
} // Shared resources, nothing to dispose
}