448 lines
14 KiB
Java
448 lines
14 KiB
Java
/* ====================================================================
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==================================================================== */
|
|
|
|
package org.apache.poi.hslf.usermodel;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.geom.Rectangle2D;
|
|
|
|
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
|
import org.apache.poi.ddf.EscherContainerRecord;
|
|
import org.apache.poi.ddf.EscherProperties;
|
|
import org.apache.poi.sl.draw.DrawPaint;
|
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
|
import org.apache.poi.sl.usermodel.ShapeType;
|
|
import org.apache.poi.sl.usermodel.StrokeStyle;
|
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
|
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
|
import org.apache.poi.sl.usermodel.TableCell;
|
|
|
|
/**
|
|
* Represents a cell in a ppt table
|
|
*/
|
|
public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFShape,HSLFTextParagraph> {
|
|
protected static final int DEFAULT_WIDTH = 100;
|
|
protected static final int DEFAULT_HEIGHT = 40;
|
|
|
|
/* package */ HSLFLine borderLeft;
|
|
/* package */ HSLFLine borderRight;
|
|
/* package */ HSLFLine borderTop;
|
|
/* package */ HSLFLine borderBottom;
|
|
|
|
/**
|
|
* The number of columns to be spanned/merged
|
|
*/
|
|
private int gridSpan = 1;
|
|
|
|
/**
|
|
* The number of columns to be spanned/merged
|
|
*/
|
|
private int rowSpan = 1;
|
|
|
|
/**
|
|
* Create a TableCell object and initialize it from the supplied Record container.
|
|
*
|
|
* @param escherRecord EscherSpContainer which holds information about this shape
|
|
* @param parent the parent of the shape
|
|
*/
|
|
protected HSLFTableCell(EscherContainerRecord escherRecord, HSLFTable parent){
|
|
super(escherRecord, parent);
|
|
}
|
|
|
|
/**
|
|
* Create a new TableCell. This constructor is used when a new shape is created.
|
|
*
|
|
* @param parent the parent of this Shape. For example, if this text box is a cell
|
|
* in a table then the parent is Table.
|
|
*/
|
|
public HSLFTableCell(HSLFTable parent){
|
|
super(parent);
|
|
|
|
setShapeType(ShapeType.RECT);
|
|
//_txtrun.setRunType(TextHeaderAtom.HALF_BODY_TYPE);
|
|
//_txtrun.getRichTextRuns()[0].setFlag(false, 0, false);
|
|
}
|
|
|
|
protected EscherContainerRecord createSpContainer(boolean isChild){
|
|
_escherContainer = super.createSpContainer(isChild);
|
|
AbstractEscherOptRecord opt = getEscherOptRecord();
|
|
setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
|
|
setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
|
|
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
|
|
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
|
|
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
|
|
|
|
return _escherContainer;
|
|
}
|
|
|
|
private void anchorBorder(BorderEdge edge, final HSLFLine line) {
|
|
if (line == null) {
|
|
return;
|
|
}
|
|
Rectangle2D cellAnchor = getAnchor();
|
|
double x,y,w,h;
|
|
switch(edge){
|
|
case top:
|
|
x = cellAnchor.getX();
|
|
y = cellAnchor.getY();
|
|
w = cellAnchor.getWidth();
|
|
h = 0;
|
|
break;
|
|
case right:
|
|
x = cellAnchor.getX() + cellAnchor.getWidth();
|
|
y = cellAnchor.getY();
|
|
w = 0;
|
|
h = cellAnchor.getHeight();
|
|
break;
|
|
case bottom:
|
|
x = cellAnchor.getX();
|
|
y = cellAnchor.getY() + cellAnchor.getHeight();
|
|
w = cellAnchor.getWidth();
|
|
h = 0;
|
|
break;
|
|
case left:
|
|
x = cellAnchor.getX();
|
|
y = cellAnchor.getY();
|
|
w = 0;
|
|
h = cellAnchor.getHeight();
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException();
|
|
}
|
|
line.setAnchor(new Rectangle2D.Double(x,y,w,h));
|
|
}
|
|
|
|
public void setAnchor(Rectangle2D anchor){
|
|
super.setAnchor(anchor);
|
|
|
|
anchorBorder(BorderEdge.top, borderTop);
|
|
anchorBorder(BorderEdge.right, borderRight);
|
|
anchorBorder(BorderEdge.bottom, borderBottom);
|
|
anchorBorder(BorderEdge.left, borderLeft);
|
|
}
|
|
|
|
@Override
|
|
public StrokeStyle getBorderStyle(final BorderEdge edge) {
|
|
final Double width = getBorderWidth(edge);
|
|
return (width == null) ? null : new StrokeStyle() {
|
|
public PaintStyle getPaint() {
|
|
return DrawPaint.createSolidPaint(getBorderColor(edge));
|
|
}
|
|
|
|
public LineCap getLineCap() {
|
|
return null;
|
|
}
|
|
|
|
public LineDash getLineDash() {
|
|
return getBorderDash(edge);
|
|
}
|
|
|
|
public LineCompound getLineCompound() {
|
|
return getBorderCompound(edge);
|
|
}
|
|
|
|
public double getLineWidth() {
|
|
return width;
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void setBorderStyle(BorderEdge edge, StrokeStyle style) {
|
|
if (style == null) {
|
|
throw new IllegalArgumentException("StrokeStyle needs to be specified.");
|
|
}
|
|
|
|
// setting the line cap is not implemented, as the border lines aren't connected
|
|
|
|
LineCompound compound = style.getLineCompound();
|
|
if (compound != null) {
|
|
setBorderCompound(edge, compound);
|
|
}
|
|
|
|
LineDash dash = style.getLineDash();
|
|
if (dash != null) {
|
|
setBorderDash(edge, dash);
|
|
}
|
|
|
|
double width = style.getLineWidth();
|
|
setBorderWidth(edge, width);
|
|
}
|
|
|
|
|
|
public Double getBorderWidth(BorderEdge edge) {
|
|
HSLFLine l;
|
|
switch (edge) {
|
|
case bottom: l = borderBottom; break;
|
|
case top: l = borderTop; break;
|
|
case right: l = borderRight; break;
|
|
case left: l = borderLeft; break;
|
|
default: throw new IllegalArgumentException();
|
|
}
|
|
return (l == null) ? null : l.getLineWidth();
|
|
}
|
|
|
|
@Override
|
|
public void setBorderWidth(BorderEdge edge, double width) {
|
|
HSLFLine l = addLine(edge);
|
|
l.setLineWidth(width);
|
|
}
|
|
|
|
public Color getBorderColor(BorderEdge edge) {
|
|
HSLFLine l;
|
|
switch (edge) {
|
|
case bottom: l = borderBottom; break;
|
|
case top: l = borderTop; break;
|
|
case right: l = borderRight; break;
|
|
case left: l = borderLeft; break;
|
|
default: throw new IllegalArgumentException();
|
|
}
|
|
return (l == null) ? null : l.getLineColor();
|
|
}
|
|
|
|
@Override
|
|
public void setBorderColor(BorderEdge edge, Color color) {
|
|
if (edge == null || color == null) {
|
|
throw new IllegalArgumentException("BorderEdge and/or Color need to be specified.");
|
|
}
|
|
|
|
HSLFLine l = addLine(edge);
|
|
l.setLineColor(color);
|
|
}
|
|
|
|
public LineDash getBorderDash(BorderEdge edge) {
|
|
HSLFLine l;
|
|
switch (edge) {
|
|
case bottom: l = borderBottom; break;
|
|
case top: l = borderTop; break;
|
|
case right: l = borderRight; break;
|
|
case left: l = borderLeft; break;
|
|
default: throw new IllegalArgumentException();
|
|
}
|
|
return (l == null) ? null : l.getLineDash();
|
|
}
|
|
|
|
@Override
|
|
public void setBorderDash(BorderEdge edge, LineDash dash) {
|
|
if (edge == null || dash == null) {
|
|
throw new IllegalArgumentException("BorderEdge and/or LineDash need to be specified.");
|
|
}
|
|
|
|
HSLFLine l = addLine(edge);
|
|
l.setLineDash(dash);
|
|
}
|
|
|
|
public LineCompound getBorderCompound(BorderEdge edge) {
|
|
HSLFLine l;
|
|
switch (edge) {
|
|
case bottom: l = borderBottom; break;
|
|
case top: l = borderTop; break;
|
|
case right: l = borderRight; break;
|
|
case left: l = borderLeft; break;
|
|
default: throw new IllegalArgumentException();
|
|
}
|
|
return (l == null) ? null : l.getLineCompound();
|
|
}
|
|
|
|
@Override
|
|
public void setBorderCompound(BorderEdge edge, LineCompound compound) {
|
|
if (edge == null || compound == null) {
|
|
throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified.");
|
|
}
|
|
|
|
HSLFLine l = addLine(edge);
|
|
l.setLineCompound(compound);
|
|
}
|
|
|
|
|
|
protected HSLFLine addLine(BorderEdge edge) {
|
|
switch (edge) {
|
|
case bottom: {
|
|
if (borderBottom == null) {
|
|
borderBottom = createBorder(edge);
|
|
HSLFTableCell c = getSiblingCell(1,0);
|
|
if (c != null) {
|
|
assert(c.borderTop == null);
|
|
c.borderTop = borderBottom;
|
|
}
|
|
}
|
|
return borderBottom;
|
|
}
|
|
case top: {
|
|
if (borderTop == null) {
|
|
borderTop = createBorder(edge);
|
|
HSLFTableCell c = getSiblingCell(-1,0);
|
|
if (c != null) {
|
|
assert(c.borderBottom == null);
|
|
c.borderBottom = borderTop;
|
|
}
|
|
}
|
|
return borderTop;
|
|
}
|
|
case right: {
|
|
if (borderRight == null) {
|
|
borderRight = createBorder(edge);
|
|
HSLFTableCell c = getSiblingCell(0,1);
|
|
if (c != null) {
|
|
assert(c.borderLeft == null);
|
|
c.borderLeft = borderRight;
|
|
}
|
|
}
|
|
return borderRight;
|
|
}
|
|
case left: {
|
|
if (borderLeft == null) {
|
|
borderLeft = createBorder(edge);
|
|
HSLFTableCell c = getSiblingCell(0,-1);
|
|
if (c != null) {
|
|
assert(c.borderRight == null);
|
|
c.borderRight = borderLeft;
|
|
}
|
|
}
|
|
return borderLeft;
|
|
}
|
|
default:
|
|
throw new IllegalArgumentException();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeBorder(BorderEdge edge) {
|
|
switch (edge) {
|
|
case bottom: {
|
|
if (borderBottom == null) break;
|
|
getParent().removeShape(borderBottom);
|
|
borderBottom = null;
|
|
HSLFTableCell c = getSiblingCell(1,0);
|
|
if (c != null) {
|
|
c.borderTop = null;
|
|
}
|
|
break;
|
|
}
|
|
case top: {
|
|
if (borderTop == null) break;
|
|
getParent().removeShape(borderTop);
|
|
borderTop = null;
|
|
HSLFTableCell c = getSiblingCell(-1,0);
|
|
if (c != null) {
|
|
c.borderBottom = null;
|
|
}
|
|
break;
|
|
}
|
|
case right: {
|
|
if (borderRight == null) break;
|
|
getParent().removeShape(borderRight);
|
|
borderRight = null;
|
|
HSLFTableCell c = getSiblingCell(0,1);
|
|
if (c != null) {
|
|
c.borderLeft = null;
|
|
}
|
|
break;
|
|
}
|
|
case left: {
|
|
if (borderLeft == null) break;
|
|
getParent().removeShape(borderLeft);
|
|
borderLeft = null;
|
|
HSLFTableCell c = getSiblingCell(0,-1);
|
|
if (c != null) {
|
|
c.borderRight = null;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
throw new IllegalArgumentException();
|
|
}
|
|
}
|
|
|
|
protected HSLFTableCell getSiblingCell(int row, int col) {
|
|
return getParent().getRelativeCell(this, row, col);
|
|
}
|
|
|
|
/**
|
|
* Create a border to format this table
|
|
*
|
|
* @return the created border
|
|
*/
|
|
private HSLFLine createBorder(BorderEdge edge) {
|
|
HSLFTable table = getParent();
|
|
HSLFLine line = new HSLFLine(table);
|
|
table.addShape(line);
|
|
|
|
AbstractEscherOptRecord opt = getEscherOptRecord();
|
|
setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
|
|
setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
|
|
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
|
|
setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
|
|
|
|
anchorBorder(edge, line);
|
|
|
|
return line;
|
|
}
|
|
|
|
protected void applyLineProperties(BorderEdge edge, HSLFLine other) {
|
|
HSLFLine line = addLine(edge);
|
|
line.setLineWidth(other.getLineWidth());
|
|
line.setLineColor(other.getLineColor());
|
|
// line.setLineCompound(other.getLineCompound());
|
|
// line.setLineDashing(other.getLineDashing());
|
|
}
|
|
|
|
@Override
|
|
public HSLFTable getParent() {
|
|
return (HSLFTable)super.getParent();
|
|
}
|
|
|
|
/**
|
|
* Set the gridSpan (aka col-span)
|
|
*
|
|
* @param gridSpan the number of columns to be spanned/merged
|
|
*
|
|
* @since POI 3.15-beta2
|
|
*/
|
|
protected void setGridSpan(int gridSpan) {
|
|
this.gridSpan = gridSpan;
|
|
}
|
|
|
|
/**
|
|
* Set the rowSpan
|
|
*
|
|
* @param rowSpan the number of rows to be spanned/merged
|
|
*
|
|
* @since POI 3.15-beta2
|
|
*/
|
|
protected void setRowSpan(int rowSpan) {
|
|
this.rowSpan = rowSpan;
|
|
}
|
|
|
|
@Override
|
|
public int getGridSpan() {
|
|
return gridSpan;
|
|
}
|
|
|
|
@Override
|
|
public int getRowSpan() {
|
|
return rowSpan;
|
|
}
|
|
|
|
@Override
|
|
public boolean isMerged() {
|
|
// if a hslf cell is merged, it won't appear in the cell matrix, i.e. it doesn't exist
|
|
// therefore this is always false
|
|
return false;
|
|
}
|
|
}
|