All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.poi.xslf.usermodel.XSLFTableCell Maven / Gradle / Ivy

Go to download

The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.

There is a newer version: 62
Show newest version
/*
 *  ====================================================================
 *    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.xslf.usermodel;

import java.awt.Color;
import java.awt.geom.Rectangle2D;

import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.XDDFLineProperties;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.*;

/**
 * Represents a cell of a table in a .pptx presentation
 */
public class XSLFTableCell extends XSLFTextShape implements TableCell {
    private CTTableCellProperties _tcPr;
    private final XSLFTable table;
    private int row, col;

    /**
     * Volatile/temporary anchor - e.g. for rendering
     */
    private Rectangle2D anchor;

    /* package */ XSLFTableCell(CTTableCell cell, XSLFTable table) {
        super(cell, table.getSheet());
        this.table = table;
    }

    @Override
    protected CTTextBody getTextBody(boolean create) {
        CTTableCell cell = getCell();
        CTTextBody txBody = cell.getTxBody();
        if (txBody == null && create) {
            XDDFTextBody body = new XDDFTextBody(this);
            cell.setTxBody(body.getXmlObject());
            txBody = cell.getTxBody();
        }
        return txBody;
    }

    static CTTableCell prototype() {
        CTTableCell cell = CTTableCell.Factory.newInstance();
        CTTableCellProperties pr = cell.addNewTcPr();
        pr.addNewLnL().addNewNoFill();
        pr.addNewLnR().addNewNoFill();
        pr.addNewLnT().addNewNoFill();
        pr.addNewLnB().addNewNoFill();
        return cell;
    }

    @SuppressWarnings("WeakerAccess")
    protected CTTableCellProperties getCellProperties(boolean create) {
        if (_tcPr == null) {
            CTTableCell cell = getCell();
            _tcPr = cell.getTcPr();
            if (_tcPr == null && create) {
                _tcPr = cell.addNewTcPr();
            }
        }
        return _tcPr;
    }

    @Override
    public void setLeftInset(double margin) {
        CTTableCellProperties pr = getCellProperties(true);
        pr.setMarL(Units.toEMU(margin));
    }

    @Override
    public void setRightInset(double margin) {
        CTTableCellProperties pr = getCellProperties(true);
        pr.setMarR(Units.toEMU(margin));
    }

    @Override
    public void setTopInset(double margin) {
        CTTableCellProperties pr = getCellProperties(true);
        pr.setMarT(Units.toEMU(margin));
    }

    @Override
    public void setBottomInset(double margin) {
        CTTableCellProperties pr = getCellProperties(true);
        pr.setMarB(Units.toEMU(margin));
    }

    private CTLineProperties getCTLine(BorderEdge edge, boolean create) {
        if (edge == null) {
            throw new IllegalArgumentException("BorderEdge needs to be specified.");
        }

        CTTableCellProperties pr = getCellProperties(create);
        if (pr == null) {
            return null;
        }

        switch (edge) {
        case bottom:
            return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null);
        case left:
            return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null);
        case top:
            return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null);
        case right:
            return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null);
        default:
            return null;
        }
    }

    public XDDFLineProperties getBorderProperties(BorderEdge edge) {
        CTLineProperties props = getCTLine(edge, false);
        return (props == null) ? null : new XDDFLineProperties(props);
    }

    public void setBorderProperties(BorderEdge edge, XDDFLineProperties properties) {
        CTLineProperties props = getCTLine(edge, true);
        if (props != null) {
            props.set(properties.getXmlObject().copy());
        }
    }

    @Override
    public void removeBorder(BorderEdge edge) {
        CTTableCellProperties pr = getCellProperties(false);
        if (pr == null) {
            return;
        }
        switch (edge) {
        case bottom:
            if (pr.isSetLnB()) {
                pr.unsetLnB();
            }
            break;
        case left:
            if (pr.isSetLnL()) {
                pr.unsetLnL();
            }
            break;
        case top:
            if (pr.isSetLnT()) {
                pr.unsetLnT();
            }
            break;
        case right:
            if (pr.isSetLnR()) {
                pr.unsetLnR();
            }
            break;
        default:
            throw new IllegalArgumentException();
        }
    }

    @Override
    public StrokeStyle getBorderStyle(final BorderEdge edge) {
        final Double width = getBorderWidth(edge);
        return (width == null) ? null : new StrokeStyle() {
            @Override
            public PaintStyle getPaint() {
                return DrawPaint.createSolidPaint(getBorderColor(edge));
            }

            @Override
            public LineCap getLineCap() {
                return getBorderCap(edge);
            }

            @Override
            public LineDash getLineDash() {
                return getBorderDash(edge);
            }

            @Override
            public LineCompound getLineCompound() {
                return getBorderCompound(edge);
            }

            @Override
            public double getLineWidth() {
                return width;
            }
        };
    }

    @Override
    public void setBorderStyle(BorderEdge edge, StrokeStyle style) {
        if (style == null) {
            throw new IllegalArgumentException("StrokeStyle needs to be specified.");
        }

        LineCap cap = style.getLineCap();
        if (cap != null) {
            setBorderCap(edge, cap);
        }

        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);
    }

    @SuppressWarnings("WeakerAccess")
    public Double getBorderWidth(BorderEdge edge) {
        CTLineProperties ln = getCTLine(edge, false);
        return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW());
    }

    @Override
    public void setBorderWidth(BorderEdge edge, double width) {
        final CTLineProperties ln = getCTLine(edge, true);
        if (ln == null) {
            return;
        }
        ln.setW(Units.toEMU(width));
    }

    private CTLineProperties setBorderDefaults(BorderEdge edge) {
        final CTLineProperties ln = getCTLine(edge, true);
        if (ln == null) {
            throw new IllegalStateException("CTLineProperties couldn't be initialized");
        }

        if (ln.isSetNoFill()) {
            ln.unsetNoFill();
        }

        if (!ln.isSetPrstDash()) {
            ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);
        }
        if (!ln.isSetCmpd()) {
            ln.setCmpd(STCompoundLine.SNG);
        }
        if (!ln.isSetAlgn()) {
            ln.setAlgn(STPenAlignment.CTR);
        }
        if (!ln.isSetCap()) {
            ln.setCap(STLineCap.FLAT);
        }
        if (!ln.isSetRound()) {
            ln.addNewRound();
        }

        if (!ln.isSetHeadEnd()) {
            CTLineEndProperties hd = ln.addNewHeadEnd();
            hd.setType(STLineEndType.NONE);
            hd.setW(STLineEndWidth.MED);
            hd.setLen(STLineEndLength.MED);
        }

        if (!ln.isSetTailEnd()) {
            CTLineEndProperties tl = ln.addNewTailEnd();
            tl.setType(STLineEndType.NONE);
            tl.setW(STLineEndWidth.MED);
            tl.setLen(STLineEndLength.MED);
        }

        return ln;
    }

    @Override
    public void setBorderColor(BorderEdge edge, Color color) {
        if (color == null) {
            throw new IllegalArgumentException("Colors need to be specified.");
        }

        CTLineProperties ln = setBorderDefaults(edge);
        CTSolidColorFillProperties fill = ln.addNewSolidFill();
        XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
        c.setColor(color);
    }

    @SuppressWarnings("WeakerAccess")
    public Color getBorderColor(BorderEdge edge) {
        CTLineProperties ln = getCTLine(edge, false);
        if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) {
            return null;
        }

        CTSolidColorFillProperties fill = ln.getSolidFill();
        XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
        return c.getColor();
    }

    @SuppressWarnings("WeakerAccess")
    public LineCompound getBorderCompound(BorderEdge edge) {
        CTLineProperties ln = getCTLine(edge, false);
        if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) {
            return null;
        }

        return LineCompound.fromOoxmlId(ln.getCmpd().intValue());
    }

    @Override
    public void setBorderCompound(BorderEdge edge, LineCompound compound) {
        if (compound == null) {
            throw new IllegalArgumentException("LineCompound need to be specified.");
        }

        CTLineProperties ln = setBorderDefaults(edge);
        ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId));
    }

    @SuppressWarnings("WeakerAccess")
    public LineDash getBorderDash(BorderEdge edge) {
        CTLineProperties ln = getCTLine(edge, false);
        if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) {
            return null;
        }

        return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue());
    }

    @Override
    public void setBorderDash(BorderEdge edge, LineDash dash) {
        if (dash == null) {
            throw new IllegalArgumentException("LineDash need to be specified.");
        }

        CTLineProperties ln = setBorderDefaults(edge);
        if (!ln.isSetPrstDash()) {
            ln.addNewPrstDash();
        }
        ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
    }

    @SuppressWarnings("WeakerAccess")
    public LineCap getBorderCap(BorderEdge edge) {
        CTLineProperties ln = getCTLine(edge, false);
        if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) {
            return null;
        }

        return LineCap.fromOoxmlId(ln.getCap().intValue());
    }

    @SuppressWarnings("WeakerAccess")
    public void setBorderCap(BorderEdge edge, LineCap cap) {
        if (cap == null) {
            throw new IllegalArgumentException("LineCap need to be specified.");
        }

        CTLineProperties ln = setBorderDefaults(edge);
        ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
    }

    /**
     * Specifies a solid color fill. The shape is filled entirely with the
     * specified color.
     *
     * @param color
     *            the solid color fill. The value of null unsets
     *            the solidFIll attribute from the underlying xml
     */
    @Override
    public void setFillColor(Color color) {
        CTTableCellProperties spPr = getCellProperties(true);
        if (color == null) {
            if (spPr.isSetSolidFill()) {
                spPr.unsetSolidFill();
            }
        } else {
            CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
            XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
            c.setColor(color);
        }
    }

    /**
     *
     * @return solid fill color of null if not set
     */
    @Override
    public Color getFillColor() {
        PaintStyle ps = getFillPaint();
        if (ps instanceof SolidPaint) {
            ColorStyle cs = ((SolidPaint) ps).getSolidColor();
            return DrawPaint.applyColorTransform(cs);
        }

        return null;
    }

    @SuppressWarnings("resource")
    @Override
    public PaintStyle getFillPaint() {
        XSLFSheet sheet = getSheet();
        XSLFTheme theme = sheet.getTheme();
        final boolean hasPlaceholder = getPlaceholder() != null;
        XmlObject props = getCellProperties(false);
        XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);
        if (fp != null) {
            PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme, hasPlaceholder);
            if (paint != null) {
                return paint;
            }
        }

        CTTablePartStyle tps = getTablePartStyle(null);
        if (tps == null || !tps.isSetTcStyle()) {
            tps = getTablePartStyle(TablePartStyle.wholeTbl);
            if (tps == null || !tps.isSetTcStyle()) {
                return null;
            }
        }

        XMLSlideShow slideShow = sheet.getSlideShow();
        CTTableStyleCellStyle tcStyle = tps.getTcStyle();
        if (tcStyle.isSetFill()) {
            props = tcStyle.getFill();
        } else if (tcStyle.isSetFillRef()) {
            props = tcStyle.getFillRef();
        } else {
            return null;
        }

        fp = XSLFPropertiesDelegate.getFillDelegate(props);
        if (fp != null) {
            PaintStyle paint = selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);
            if (paint != null) {
                return paint;
            }
        }

        return null;
    }

    /**
     * Retrieves the part style depending on the location of this cell
     *
     * @param tablePartStyle
     *            the part to be returned, usually this is null and only set
     *            when used as a helper method
     * @return the table part style
     */
    private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) {
        CTTable ct = table.getCTTable();
        if (!ct.isSetTblPr()) {
            return null;
        }

        CTTableProperties pr = ct.getTblPr();
        boolean bandRow = (pr.isSetBandRow() && pr.getBandRow());
        boolean firstRow = (pr.isSetFirstRow() && pr.getFirstRow());
        boolean lastRow = (pr.isSetLastRow() && pr.getLastRow());
        boolean bandCol = (pr.isSetBandCol() && pr.getBandCol());
        boolean firstCol = (pr.isSetFirstCol() && pr.getFirstCol());
        boolean lastCol = (pr.isSetLastCol() && pr.getLastCol());

        TablePartStyle tps;
        if (tablePartStyle != null) {
            tps = tablePartStyle;
        } else if (row == 0 && firstRow) {
            tps = TablePartStyle.firstRow;
        } else if (row == table.getNumberOfRows() - 1 && lastRow) {
            tps = TablePartStyle.lastRow;
        } else if (col == 0 && firstCol) {
            tps = TablePartStyle.firstCol;
        } else if (col == table.getNumberOfColumns() - 1 && lastCol) {
            tps = TablePartStyle.lastCol;
        } else {
            tps = TablePartStyle.wholeTbl;

            int br = row + (firstRow ? 1 : 0);
            int bc = col + (firstCol ? 1 : 0);
            if (bandRow && (br & 1) == 0) {
                tps = TablePartStyle.band1H;
            } else if (bandCol && (bc & 1) == 0) {
                tps = TablePartStyle.band1V;
            }
        }

        XSLFTableStyle tabStyle = table.getTableStyle();
        if (tabStyle == null) {
            return null;
        }

        CTTablePartStyle part = tabStyle.getTablePartStyle(tps);
        return (part == null) ? tabStyle.getTablePartStyle(TablePartStyle.wholeTbl) : part;
    }

    void setGridSpan(int gridSpan_) {
        getCell().setGridSpan(gridSpan_);
    }

    @Override
    public int getGridSpan() {
        CTTableCell c = getCell();
        return (c.isSetGridSpan()) ? c.getGridSpan() : 1;
    }

    void setRowSpan(int rowSpan_) {
        getCell().setRowSpan(rowSpan_);
    }

    @Override
    public int getRowSpan() {
        CTTableCell c = getCell();
        return (c.isSetRowSpan()) ? c.getRowSpan() : 1;
    }

    void setHMerge() {
        getCell().setHMerge(true);
    }

    void setVMerge() {
        getCell().setVMerge(true);
    }

    @Override
    public void setVerticalAlignment(VerticalAlignment anchor) {
        CTTableCellProperties cellProps = getCellProperties(true);
        if (anchor == null) {
            if (cellProps.isSetAnchor()) {
                cellProps.unsetAnchor();
            }
        } else {
            cellProps.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
        }
    }

    @Override
    public VerticalAlignment getVerticalAlignment() {
        CTTableCellProperties cellProps = getCellProperties(false);

        VerticalAlignment align = VerticalAlignment.TOP;
        if (cellProps != null && cellProps.isSetAnchor()) {
            int ival = cellProps.getAnchor().intValue();
            align = VerticalAlignment.values()[ival - 1];
        }
        return align;
    }

    /**
     * @since POI 3.15-beta2
     */
    @Override
    public void setTextDirection(TextDirection orientation) {
        CTTableCellProperties cellProps = getCellProperties(true);
        if (orientation == null) {
            if (cellProps.isSetVert()) {
                cellProps.unsetVert();
            }
        } else {
            STTextVerticalType.Enum vt;
            switch (orientation) {
            default:
            case HORIZONTAL:
                vt = STTextVerticalType.HORZ;
                break;
            case VERTICAL:
                vt = STTextVerticalType.VERT;
                break;
            case VERTICAL_270:
                vt = STTextVerticalType.VERT_270;
                break;
            case STACKED:
                vt = STTextVerticalType.WORD_ART_VERT;
                break;
            }

            cellProps.setVert(vt);
        }
    }

    /**
     * @since POI 3.15-beta2
     */
    @Override
    public TextDirection getTextDirection() {
        CTTableCellProperties cellProps = getCellProperties(false);

        STTextVerticalType.Enum orientation;
        if (cellProps != null && cellProps.isSetVert()) {
            orientation = cellProps.getVert();
        } else {
            orientation = STTextVerticalType.HORZ;
        }

        switch (orientation.intValue()) {
        default:
        case STTextVerticalType.INT_HORZ:
            return TextDirection.HORIZONTAL;
        case STTextVerticalType.INT_VERT:
        case STTextVerticalType.INT_EA_VERT:
        case STTextVerticalType.INT_MONGOLIAN_VERT:
            return TextDirection.VERTICAL;
        case STTextVerticalType.INT_VERT_270:
            return TextDirection.VERTICAL_270;
        case STTextVerticalType.INT_WORD_ART_VERT:
        case STTextVerticalType.INT_WORD_ART_VERT_RTL:
            return TextDirection.STACKED;
        }
    }

    private CTTableCell getCell() {
        return (CTTableCell) getXmlObject();
    }

    /* package */ void setRowColIndex(int row, int col) {
        this.row = row;
        this.col = col;
    }

    /**
     * Return a fake-xfrm which is used for calculating the text height
     */
    protected CTTransform2D getXfrm() {
        Rectangle2D anc = getAnchor();
        CTTransform2D xfrm = CTTransform2D.Factory.newInstance();
        CTPoint2D off = xfrm.addNewOff();
        off.setX(Units.toEMU(anc.getX()));
        off.setY(Units.toEMU(anc.getY()));
        CTPositiveSize2D size = xfrm.addNewExt();
        size.setCx(Units.toEMU(anc.getWidth()));
        size.setCy(Units.toEMU(anc.getHeight()));
        return xfrm;
    }

    /**
     * There's no real anchor for table cells - this method is used to
     * temporarily store the location of the cell for a later retrieval, e.g.
     * for rendering
     *
     * @since POI 3.15-beta2
     */
    @Override
    public void setAnchor(Rectangle2D anchor) {
        if (this.anchor == null) {
            this.anchor = (Rectangle2D) anchor.clone();
        } else {
            this.anchor.setRect(anchor);
        }
    }

    /**
     * @since POI 3.15-beta2
     */
    @Override
    public Rectangle2D getAnchor() {
        if (anchor == null) {
            table.updateCellAnchor();
        }
        // anchor should be set, after updateCellAnchor is through
        assert (anchor != null);
        return anchor;
    }

    /**
     * @since POI 3.15-beta2
     */
    @Override
    public boolean isMerged() {
        CTTableCell c = getCell();
        return (c.isSetHMerge() && c.getHMerge()) || (c.isSetVMerge() && c.getVMerge());
    }

    /**
     * @since POI 3.15-beta2
     */
    @Override
    protected XSLFCellTextParagraph newTextParagraph(CTTextParagraph p) {
        return new XSLFCellTextParagraph(p, this);
    }

    @Override
    protected XmlObject getShapeProperties() {
        return getCellProperties(false);
    }

    /**
     * @since POI 3.15-beta2
     */
    private final class XSLFCellTextParagraph extends XSLFTextParagraph {
        private XSLFCellTextParagraph(CTTextParagraph p, XSLFTextShape shape) {
            super(p, shape);
        }

        @Override
        protected XSLFCellTextRun newTextRun(XmlObject r) {
            return new XSLFCellTextRun(r, this);
        }
    }

    /**
     * @since POI 3.15-beta2
     */
    private final class XSLFCellTextRun extends XSLFTextRun {
        private XSLFCellTextRun(XmlObject r, XSLFTextParagraph p) {
            super(r, p);
        }

        @Override
        public PaintStyle getFontColor() {
            CTTableStyleTextStyle txStyle = getTextStyle();
            if (txStyle == null) {
                return super.getFontColor();
            }

            CTSchemeColor phClr = null;
            CTFontReference fontRef = txStyle.getFontRef();
            if (fontRef != null) {
                phClr = fontRef.getSchemeClr();
            }

            XSLFTheme theme = getSheet().getTheme();
            final XSLFColor c = new XSLFColor(txStyle, theme, phClr, getSheet());
            return DrawPaint.createSolidPaint(c.getColorStyle());
        }

        @Override
        public boolean isBold() {
            CTTableStyleTextStyle txStyle = getTextStyle();
            if (txStyle == null) {
                return super.isBold();
            } else {
                return txStyle.isSetB() && txStyle.getB().intValue() == STOnOffStyleType.INT_ON;
            }
        }

        @Override
        public boolean isItalic() {
            CTTableStyleTextStyle txStyle = getTextStyle();
            if (txStyle == null) {
                return super.isItalic();
            } else {
                return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON;
            }
        }

        private CTTableStyleTextStyle getTextStyle() {
            CTTablePartStyle tps = getTablePartStyle(null);
            if (tps == null || !tps.isSetTcTxStyle()) {
                tps = getTablePartStyle(TablePartStyle.wholeTbl);
            }
            return (tps == null) ? null : tps.getTcTxStyle();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy