be.quodlibet.boxable.Cell Maven / Gradle / Ivy
Show all versions of boxable Show documentation
/*
Quodlibet.be
*/
package be.quodlibet.boxable;
import java.awt.Color;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import be.quodlibet.boxable.line.LineStyle;
import be.quodlibet.boxable.text.WrappingFunction;
import be.quodlibet.boxable.utils.FontUtils;
public class Cell {
private float width;
private Float height;
private String text;
private PDFont font = PDType1Font.HELVETICA;
private PDFont fontBold = PDType1Font.HELVETICA_BOLD;
private float fontSize = 8;
private Color fillColor;
private Color textColor = Color.BLACK;
private final Row row;
private WrappingFunction wrappingFunction;
private boolean isHeaderCell = false;
private boolean isColspanCell = false;
// default padding
private float leftPadding = 5f;
private float rightPadding = 5f;
private float topPadding = 5f;
private float bottomPadding = 5f;
// default border
private LineStyle leftBorderStyle = new LineStyle(Color.BLACK, 1);
private LineStyle rightBorderStyle = new LineStyle(Color.BLACK, 1);
private LineStyle topBorderStyle = new LineStyle(Color.BLACK, 1);
private LineStyle bottomBorderStyle = new LineStyle(Color.BLACK, 1);
private Paragraph paragraph = null;
private float lineSpacing = 1;
private boolean textRotated = false;
private HorizontalAlignment align;
private VerticalAlignment valign;
float horizontalFreeSpace = 0;
float verticalFreeSpace = 0;
/**
*
* Constructs a cell with the default alignment
* {@link VerticalAlignment#TOP} {@link HorizontalAlignment#LEFT}.
*
*
* @param row
* @param width
* @param text
* @param isCalculated
* @see Cell#Cell(Row, float, String, boolean, HorizontalAlignment,
* VerticalAlignment)
*/
Cell(Row row, float width, String text, boolean isCalculated) {
this(row, width, text, isCalculated, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
}
/**
*
* Constructs a cell.
*
*
* @param row
* The parent row
* @param width
* absolute width in points or in % of table width (depending on
* the parameter {@code isCalculated})
* @param text
* The text content of the cell
* @param isCalculated
* If {@code true}, the width is interpreted in % to the table
* width
* @param align
* The {@link HorizontalAlignment} of the cell content
* @param valign
* The {@link VerticalAlignment} of the cell content
* @see Cell#Cell(Row, float, String, boolean)
*/
Cell(Row row, float width, String text, boolean isCalculated, HorizontalAlignment align,
VerticalAlignment valign) {
this.row = row;
if (isCalculated) {
double calclulatedWidth = ((row.getWidth() * width) / 100);
this.width = (float) calclulatedWidth;
} else {
this.width = width;
}
if (getWidth() > row.getWidth()) {
throw new IllegalArgumentException(
"Cell Width=" + getWidth() + " can't be bigger than row width=" + row.getWidth());
}
//check if we have new default font
if(!FontUtils.getDefaultfonts().isEmpty()){
font = FontUtils.getDefaultfonts().get("font");
fontBold = FontUtils.getDefaultfonts().get("fontBold");
}
this.text = text == null ? "" : text;
this.align = align;
this.valign = valign;
this.wrappingFunction = null;
}
/**
*
* Retrieves cell's text {@link Color}. Default color is black.
*
*
* @return {@link Color} of the cell's text
*/
public Color getTextColor() {
return textColor;
}
/**
*
* Sets cell's text {@link Color}.
*
*
* @param textColor
* designated text {@link Color}
*/
public void setTextColor(Color textColor) {
this.textColor = textColor;
}
/**
*
* Gets fill (background) {@link Color} for the current cell.
*
*
* @return Fill {@link Color} for the cell
*/
public Color getFillColor() {
return fillColor;
}
/**
*
* Sets fill (background) {@link Color} for the current cell.
*
*
* @param fillColor
* Fill {@link Color} for the cell
*/
public void setFillColor(Color fillColor) {
this.fillColor = fillColor;
}
/**
*
* Gets cell's width.
*
*
* @return Cell's width
*/
public float getWidth() {
return width;
}
/**
*
* Gets cell's width without (left,right) padding.
*
* @return Inner cell's width
*/
public float getInnerWidth() {
return getWidth() - getLeftPadding() - getRightPadding()
- (leftBorderStyle == null ? 0 : leftBorderStyle.getWidth())
- (rightBorderStyle == null ? 0 : rightBorderStyle.getWidth());
}
/**
*
* Gets cell's height without (top,bottom) padding.
*
* @return Inner cell's height
*/
public float getInnerHeight() {
return getHeight() - getBottomPadding() - getTopPadding()
- (topBorderStyle == null ? 0 : topBorderStyle.getWidth())
- (bottomBorderStyle == null ? 0 : bottomBorderStyle.getWidth());
}
/**
*
* Retrieves text from current cell
*
*
* @return cell's text
*/
public String getText() {
return text;
}
/**
*
* Sets cell's text value
*
*
* @param text
* Text value of the cell
*/
public void setText(String text) {
this.text = text;
// paragraph invalidated
paragraph = null;
}
/**
*
* Gets appropriate {@link PDFont} for current cell.
*
*
* @return {@link PDFont} for current cell
* @throws IllegalArgumentException
* if font
is not set.
*/
public PDFont getFont() {
if (font == null) {
throw new IllegalArgumentException("Font not set.");
}
if (isHeaderCell) {
return fontBold;
} else {
return font;
}
}
/**
*
* Sets appropriate {@link PDFont} for current cell.
*
*
* @param font
* {@link PDFont} for current cell
*/
public void setFont(PDFont font) {
this.font = font;
// paragraph invalidated
paragraph = null;
}
/**
*
* Gets {@link PDFont} size for current cell (in points).
*
*
* @return {@link PDFont} size for current cell (in points).
*/
public float getFontSize() {
return fontSize;
}
/**
*
* Sets {@link PDFont} size for current cell (in points).
*
*
* @param fontSize
* {@link PDFont} size for current cell (in points).
*/
public void setFontSize(float fontSize) {
this.fontSize = fontSize;
// paragraph invalidated
paragraph = null;
}
/**
*
* Retrieves a valid {@link Paragraph} depending of cell's {@link PDFont}
* and value rotation.
*
*
*
* If cell has rotated value then {@link Paragraph} width is depending of
* {@link Cell#getInnerHeight()} otherwise {@link Cell#getInnerWidth()}
*
*
*
* @return Cell's {@link Paragraph}
*/
public Paragraph getParagraph() {
if (paragraph == null) {
// if it is header cell then use font bold
if (isHeaderCell) {
if (isTextRotated()) {
paragraph = new Paragraph(text, fontBold, fontSize, getInnerHeight(), align, textColor, null,
wrappingFunction, lineSpacing);
} else {
paragraph = new Paragraph(text, fontBold, fontSize, getInnerWidth(), align, textColor, null,
wrappingFunction, lineSpacing);
}
} else {
if (isTextRotated()) {
paragraph = new Paragraph(text, font, fontSize, getInnerHeight(), align, textColor, null,
wrappingFunction, lineSpacing);
} else {
paragraph = new Paragraph(text, font, fontSize, getInnerWidth(), align, textColor, null,
wrappingFunction, lineSpacing);
}
}
}
return paragraph;
}
public float getExtraWidth() {
return this.row.getLastCellExtraWidth() + getWidth();
}
/**
*
* Gets the cell's height according to {@link Row}'s height
*
*
* @return {@link Row}'s height
*/
public float getHeight() {
return row.getHeight();
}
/**
*
* Gets the height of the single cell, opposed to {@link #getHeight()},
* which returns the row's height.
*
*
* Depending of rotated/normal cell's value there is two cases for
* calculation:
*
*
* - Rotated value - cell's height is equal to overall text length in the
* cell with necessery paddings (top,bottom)
* - Normal value - cell's height is equal to {@link Paragraph}'s height
* with necessery paddings (top,bottom)
*
*
* @return Cell's height
* @throws IllegalStateException
* if font
is not set.
*/
public float getCellHeight() {
if (height != null) {
return height;
}
if (isTextRotated()) {
try {
// TODO: maybe find more optimal way then this
return getFont().getStringWidth(getText()) / 1000 * getFontSize() + getTopPadding()
+ (getTopBorder() == null ? 0 : getTopBorder().getWidth()) + getBottomPadding()
+ (getBottomBorder() == null ? 0 : getBottomBorder().getWidth());
} catch (final IOException e) {
throw new IllegalStateException("Font not set.", e);
}
} else {
return getTextHeight() + getTopPadding() + getBottomPadding()
+ (getTopBorder() == null ? 0 : getTopBorder().getWidth())
+ (getBottomBorder() == null ? 0 : getBottomBorder().getWidth());
}
}
/**
*
* Sets the height of the single cell.
*
*
* @param height
* Cell's height
*/
public void setHeight(final Float height) {
this.height = height;
}
/**
*
* Gets {@link Paragraph}'s height
*
*
* @return {@link Paragraph}'s height
*/
public float getTextHeight() {
return getParagraph().getHeight();
}
/**
*
* Gets {@link Paragraph}'s width
*
*
* @return {@link Paragraph}'s width
*/
public float getTextWidth() {
return getParagraph().getWidth();
}
/**
*
* Gets cell's left padding (in points).
*
*
* @return Cell's left padding (in points).
*/
public float getLeftPadding() {
return leftPadding;
}
/**
*
* Sets cell's left padding (in points)
*
*
* @param cellLeftPadding
* Cell's left padding (in points).
*/
public void setLeftPadding(float cellLeftPadding) {
this.leftPadding = cellLeftPadding;
// paragraph invalidated
paragraph = null;
}
/**
*
* Gets cell's right padding (in points).
*
*
* @return Cell's right padding (in points).
*/
public float getRightPadding() {
return rightPadding;
}
/**
*
* Sets cell's right padding (in points)
*
*
* @param cellRightPadding
* Cell's right padding (in points).
*/
public void setRightPadding(float cellRightPadding) {
this.rightPadding = cellRightPadding;
// paragraph invalidated
paragraph = null;
}
/**
*
* Gets cell's top padding (in points).
*
*
* @return Cell's top padding (in points).
*/
public float getTopPadding() {
return topPadding;
}
/**
*
* Sets cell's top padding (in points)
*
*
* @param cellTopPadding
* Cell's top padding (in points).
*/
public void setTopPadding(float cellTopPadding) {
this.topPadding = cellTopPadding;
}
/**
*
* Gets cell's bottom padding (in points).
*
*
* @return Cell's bottom padding (in points).
*/
public float getBottomPadding() {
return bottomPadding;
}
/**
*
* Sets cell's bottom padding (in points)
*
*
* @param cellBottomPadding
* Cell's bottom padding (in points).
*/
public void setBottomPadding(float cellBottomPadding) {
this.bottomPadding = cellBottomPadding;
}
/**
*
* Gets free vertical space of cell.
*
*
*
* If cell has rotated value then free vertical space is equal inner cell's
* height ({@link #getInnerHeight()}) subtracted to the longest line of
* rotated {@link Paragraph} otherwise it's just cell's inner height (
* {@link #getInnerHeight()}) subtracted with width of the normal
* {@link Paragraph}.
*
*
* @return Free vertical space of the cell's.
*/
public float getVerticalFreeSpace() {
if (isTextRotated()) {
// need to calculate max line width so we just iterating through
// lines
for (String line : getParagraph().getLines()) {
}
return getInnerHeight() - getParagraph().getMaxLineWidth();
} else {
return getInnerHeight() - getTextHeight();
}
}
/**
*
* Gets free horizontal space of cell.
*
*
*
* If cell has rotated value then free horizontal space is equal cell's
* inner width ({@link #getInnerWidth()}) subtracted to the
* {@link Paragraph}'s height otherwise it's just cell's
* {@link #getInnerWidth()} subtracted with width of longest line in normal
* {@link Paragraph}.
*
*
* @return Free vertical space of the cell's.
*/
public float getHorizontalFreeSpace() {
if (isTextRotated()) {
return getInnerWidth() - getTextHeight();
} else {
return getInnerWidth() - getParagraph().getMaxLineWidth();
}
}
public HorizontalAlignment getAlign() {
return align;
}
public VerticalAlignment getValign() {
return valign;
}
public boolean isHeaderCell() {
return isHeaderCell;
}
public void setHeaderCell(boolean isHeaderCell) {
this.isHeaderCell = isHeaderCell;
}
public WrappingFunction getWrappingFunction() {
return getParagraph().getWrappingFunction();
}
public void setWrappingFunction(WrappingFunction wrappingFunction) {
this.wrappingFunction = wrappingFunction;
// paragraph invalidated
paragraph = null;
}
public LineStyle getLeftBorder() {
return leftBorderStyle;
}
public LineStyle getRightBorder() {
return rightBorderStyle;
}
public LineStyle getTopBorder() {
return topBorderStyle;
}
public LineStyle getBottomBorder() {
return bottomBorderStyle;
}
public void setLeftBorderStyle(LineStyle leftBorder) {
this.leftBorderStyle = leftBorder;
}
public void setRightBorderStyle(LineStyle rightBorder) {
this.rightBorderStyle = rightBorder;
}
public void setTopBorderStyle(LineStyle topBorder) {
this.topBorderStyle = topBorder;
}
public void setBottomBorderStyle(LineStyle bottomBorder) {
this.bottomBorderStyle = bottomBorder;
}
/**
*
* Easy setting for cell border style.
*
* @param border
* It is {@link LineStyle} for all borders
* @see LineStyle Rendering line attributes
*/
public void setBorderStyle(LineStyle border) {
this.leftBorderStyle = border;
this.rightBorderStyle = border;
this.topBorderStyle = border;
this.bottomBorderStyle = border;
}
public boolean isTextRotated() {
return textRotated;
}
public void setTextRotated(boolean textRotated) {
this.textRotated = textRotated;
}
public PDFont getFontBold() {
return fontBold;
}
/**
*
* Sets the {@linkplain PDFont font} used for bold text, for example in
* {@linkplain #isHeaderCell() header cells}.
*
*
* @param fontBold
* The {@linkplain PDFont font} to use for bold text
*/
public void setFontBold(final PDFont fontBold) {
this.fontBold = fontBold;
}
public boolean isColspanCell() {
return isColspanCell;
}
public void setColspanCell(boolean isColspanCell) {
this.isColspanCell = isColspanCell;
}
public void setAlign(HorizontalAlignment align) {
this.align = align;
}
public void setValign(VerticalAlignment valign) {
this.valign = valign;
}
/**
*
* Copies the style of an existing cell to this cell
*
*
* @param sourceCell Source {@link Cell} from which cell style will be copied.
*/
public void copyCellStyle(Cell sourceCell) {
Boolean leftBorder = this.leftBorderStyle == null;
setBorderStyle(sourceCell.getTopBorder());
if (leftBorder) {
this.leftBorderStyle = null;// if left border wasn't set, don't set
// it now
}
this.font = sourceCell.getFont();// otherwise paragraph gets invalidated
this.fontBold = sourceCell.getFontBold();
this.fontSize = sourceCell.getFontSize();
setFillColor(sourceCell.getFillColor());
setTextColor(sourceCell.getTextColor());
setAlign(sourceCell.getAlign());
setValign(sourceCell.getValign());
}
/**
*
* Compares the style of a cell with another cell
*
*
* @param sourceCell Source {@link Cell} which will be used for style comparation
* @return boolean if source cell has the same style
*/
public Boolean hasSameStyle(Cell sourceCell) {
if (!sourceCell.getTopBorder().equals(getTopBorder())) {
return false;
}
if (!sourceCell.getFont().equals(getFont())) {
return false;
}
if (!sourceCell.getFontBold().equals(getFontBold())) {
return false;
}
if (!sourceCell.getFillColor().equals(getFillColor())) {
return false;
}
if (!sourceCell.getTextColor().equals(getTextColor())) {
return false;
}
if (!sourceCell.getAlign().equals(getAlign())) {
return false;
}
if (!sourceCell.getValign().equals(getValign())) {
return false;
}
return true;
}
public void setWidth(float width) {
this.width = width;
}
public float getLineSpacing() {
return lineSpacing;
}
public void setLineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing;
}
}