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

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

There is a newer version: 5.2.5
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.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.ParagraphPropertyFetcher;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;

/**
 * Represents a paragraph of text within the containing text body.
 * The paragraph is the highest level text separation mechanism.
 *
 * @since POI-3.8
 */
@Beta
public class XSLFTextParagraph implements TextParagraph {
    private final CTTextParagraph _p;
    private final List _runs;
    private final XSLFTextShape _shape;

    XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
        _p = p;
        _runs = new ArrayList();
        _shape = shape;

        for(XmlObject ch : _p.selectPath("*")){
            if(ch instanceof CTRegularTextRun){
                CTRegularTextRun r = (CTRegularTextRun)ch;
                _runs.add(newTextRun(r));
            } else if (ch instanceof CTTextLineBreak){
                CTTextLineBreak br = (CTTextLineBreak)ch;
                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
                r.setRPr(br.getRPr());
                r.setT("\n");
                _runs.add(newTextRun(r));
            } else if (ch instanceof CTTextField){
                CTTextField f = (CTTextField)ch;
                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
                r.setRPr(f.getRPr());
                r.setT(f.getT());
                _runs.add(newTextRun(r));
            }
        }
    }

    public String getText(){
        StringBuilder out = new StringBuilder();
        for (XSLFTextRun r : _runs) {
            out.append(r.getRawText());
        }
        return out.toString();
    }

    String getRenderableText(){
        StringBuilder out = new StringBuilder();
        for (XSLFTextRun r : _runs) {
            out.append(r.getRenderableText());
        }
        return out.toString();
    }

    @Internal
    public CTTextParagraph getXmlObject(){
        return _p;
    }

    public XSLFTextShape getParentShape() {
        return _shape;

    }

    @Override
    public List getTextRuns(){
        return _runs;
    }

    public Iterator iterator(){
        return _runs.iterator();
    }

    /**
     * Add a new run of text
     *
     * @return a new run of text
     */
    public XSLFTextRun addNewTextRun(){
        CTRegularTextRun r = _p.addNewR();
        CTTextCharacterProperties rPr = r.addNewRPr();
        rPr.setLang("en-US");
        XSLFTextRun run = newTextRun(r);
        _runs.add(run);
        return run;
    }

    /**
     * Insert a line break
     *
     * @return text run representing this line break ('\n')
     */
    public XSLFTextRun addLineBreak(){
        CTTextLineBreak br = _p.addNewBr();
        CTTextCharacterProperties brProps = br.addNewRPr();
        if(_runs.size() > 0){
            // by default line break has the font size of the last text run
            CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(true);
            brProps.set(prevRun);
        }
        CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
        r.setRPr(brProps);
        r.setT("\n");
        XSLFTextRun run = new XSLFLineBreak(r, this, brProps);
        _runs.add(run);
        return run;
    }

    @Override
    public TextAlign getTextAlign(){
        ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){
            public boolean fetch(CTTextParagraphProperties props){
                if(props.isSetAlgn()){
                    TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1];
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchParagraphProperty(fetcher);
        return fetcher.getValue();
    }

    @Override
    public void setTextAlign(TextAlign align) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(align == null) {
            if(pr.isSetAlgn()) pr.unsetAlgn();
        } else {
            pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));
        }
    }

    @Override
    public FontAlign getFontAlign(){
        ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){
            public boolean fetch(CTTextParagraphProperties props){
                if(props.isSetFontAlgn()){
                    FontAlign val = FontAlign.values()[props.getFontAlgn().intValue() - 1];
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchParagraphProperty(fetcher);
        return fetcher.getValue();
    }

    /**
     * Specifies the font alignment that is to be applied to the paragraph.
     * Possible values for this include auto, top, center, baseline and bottom.
     * see {@link org.apache.poi.sl.usermodel.TextParagraph.FontAlign}.
     *
     * @param align font align
     */
    public void setFontAlign(FontAlign align){
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(align == null) {
            if(pr.isSetFontAlgn()) pr.unsetFontAlgn();
        } else {
            pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1));
        }
    }

    

    /**
     * @return the font to be used on bullet characters within a given paragraph
     */
    public String getBulletFont(){
        ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){
            public boolean fetch(CTTextParagraphProperties props){
                if(props.isSetBuFont()){
                    setValue(props.getBuFont().getTypeface());
                    return true;
                }
                return false;
            }
        };
        fetchParagraphProperty(fetcher);
        return fetcher.getValue();
    }

    public void setBulletFont(String typeface){
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont();
        font.setTypeface(typeface);
    }

    /**
     * @return the character to be used in place of the standard bullet point
     */
    public String getBulletCharacter(){
        ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){
            public boolean fetch(CTTextParagraphProperties props){
                if(props.isSetBuChar()){
                    setValue(props.getBuChar().getChar());
                    return true;
                }
                return false;
            }
        };
        fetchParagraphProperty(fetcher);
        return fetcher.getValue();
    }

    public void setBulletCharacter(String str){
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar();
        c.setChar(str);
    }

    /**
     *
     * @return the color of bullet characters within a given paragraph.
     * A null value means to use the text font color.
     */
    public PaintStyle getBulletFontColor(){
        final XSLFTheme theme = getParentShape().getSheet().getTheme();
        ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){
            public boolean fetch(CTTextParagraphProperties props){
                if(props.isSetBuClr()){
                    XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
                    setValue(c.getColor());
                    return true;
                }
                return false;
            }
        };
        fetchParagraphProperty(fetcher);
        Color col = fetcher.getValue();
        return (col == null) ? null : DrawPaint.createSolidPaint(col);
    }

    public void setBulletFontColor(Color color) {
        setBulletFontColor(DrawPaint.createSolidPaint(color));
    }
    
    
    /**
     * Set the color to be used on bullet characters within a given paragraph.
     *
     * @param color the bullet color
     */
    public void setBulletFontColor(PaintStyle color) {
        if (!(color instanceof SolidPaint)) {
            throw new IllegalArgumentException("Currently XSLF only supports SolidPaint");
        }

        // TODO: implement setting bullet color to null
        SolidPaint sp = (SolidPaint)color;
        Color col = DrawPaint.applyColorTransform(sp.getSolidColor());
        
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();
        CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();
        clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()});
    }

    /**
     * Returns the bullet size that is to be used within a paragraph.
     * This may be specified in two different ways, percentage spacing and font point spacing:
     * 

* If bulletSize >= 0, then bulletSize is a percentage of the font size. * If bulletSize < 0, then it specifies the size in points *

* * @return the bullet size */ public Double getBulletFontSize(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetBuSzPct()){ setValue(props.getBuSzPct().getVal() * 0.001); return true; } if(props.isSetBuSzPts()){ setValue( - props.getBuSzPts().getVal() * 0.01); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } /** * Sets the bullet size that is to be used within a paragraph. * This may be specified in two different ways, percentage spacing and font point spacing: *

* If bulletSize >= 0, then bulletSize is a percentage of the font size. * If bulletSize < 0, then it specifies the size in points *

*/ public void setBulletFontSize(double bulletSize){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if(bulletSize >= 0) { CTTextBulletSizePercent pt = pr.isSetBuSzPct() ? pr.getBuSzPct() : pr.addNewBuSzPct(); pt.setVal((int)(bulletSize*1000)); if(pr.isSetBuSzPts()) pr.unsetBuSzPts(); } else { CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts(); pt.setVal((int)(-bulletSize*100)); if(pr.isSetBuSzPct()) pr.unsetBuSzPct(); } } /** * @return the auto numbering scheme, or null if not defined */ public AutoNumberingScheme getAutoNumberingScheme() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()) { public boolean fetch(CTTextParagraphProperties props) { if (props.isSetBuAutoNum()) { AutoNumberingScheme ans = AutoNumberingScheme.forOoxmlID(props.getBuAutoNum().getType().intValue()); if (ans != null) { setValue(ans); return true; } } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } /** * @return the auto numbering starting number, or null if not defined */ public Integer getAutoNumberingStartAt() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()) { public boolean fetch(CTTextParagraphProperties props) { if (props.isSetBuAutoNum()) { if (props.getBuAutoNum().isSetStartAt()) { setValue(props.getBuAutoNum().getStartAt()); return true; } } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } @Override public void setIndent(Double indent){ if ((indent == null) && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if(indent == null) { if(pr.isSetIndent()) pr.unsetIndent(); } else { pr.setIndent(Units.toEMU(indent)); } } @Override public Double getIndent() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetIndent()){ setValue(Units.toPoints(props.getIndent())); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } @Override public void setLeftMargin(Double leftMargin){ if (leftMargin == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if (leftMargin == null) { if(pr.isSetMarL()) pr.unsetMarL(); } else { pr.setMarL(Units.toEMU(leftMargin)); } } /** * @return the left margin (in points) of the paragraph, null if unset */ @Override public Double getLeftMargin(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetMarL()){ double val = Units.toPoints(props.getMarL()); setValue(val); return true; } return false; } }; fetchParagraphProperty(fetcher); // if the marL attribute is omitted, then a value of 347663 is implied return fetcher.getValue(); } @Override public void setRightMargin(Double rightMargin){ if (rightMargin == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if(rightMargin == null) { if(pr.isSetMarR()) pr.unsetMarR(); } else { pr.setMarR(Units.toEMU(rightMargin)); } } /** * * @return the right margin of the paragraph, null if unset */ @Override public Double getRightMargin(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetMarR()){ double val = Units.toPoints(props.getMarR()); setValue(val); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } @Override public Double getDefaultTabSize(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetDefTabSz()){ double val = Units.toPoints(props.getDefTabSz()); setValue(val); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } public double getTabStop(final int idx){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetTabLst()){ CTTextTabStopList tabStops = props.getTabLst(); if(idx < tabStops.sizeOfTabArray() ) { CTTextTabStop ts = tabStops.getTabArray(idx); double val = Units.toPoints(ts.getPos()); setValue(val); return true; } } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue() == null ? 0. : fetcher.getValue(); } public void addTabStop(double value){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextTabStopList tabStops = pr.isSetTabLst() ? pr.getTabLst() : pr.addNewTabLst(); tabStops.addNewTab().setPos(Units.toEMU(value)); } @Override public void setLineSpacing(Double lineSpacing){ if (lineSpacing == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if(lineSpacing == null) { if (pr.isSetLnSpc()) pr.unsetLnSpc(); } else { CTTextSpacing spc = (pr.isSetLnSpc()) ? pr.getLnSpc() : pr.addNewLnSpc(); if (lineSpacing >= 0) { (spc.isSetSpcPct() ? spc.getSpcPct() : spc.addNewSpcPct()).setVal((int)(lineSpacing*1000)); if (spc.isSetSpcPts()) spc.unsetSpcPts(); } else { (spc.isSetSpcPts() ? spc.getSpcPts() : spc.addNewSpcPts()).setVal((int)(-lineSpacing*100)); if (spc.isSetSpcPct()) spc.unsetSpcPct(); } } } @Override public Double getLineSpacing(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetLnSpc()){ CTTextSpacing spc = props.getLnSpc(); if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 ); else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); return true; } return false; } }; fetchParagraphProperty(fetcher); Double lnSpc = fetcher.getValue(); if (lnSpc != null && lnSpc > 0) { // check if the percentage value is scaled CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit(); if(normAutofit != null) { double scale = 1 - (double)normAutofit.getLnSpcReduction() / 100000; lnSpc *= scale; } } return lnSpc; } @Override public void setSpaceBefore(Double spaceBefore){ if (spaceBefore == null && !_p.isSetPPr()) { return; } // unset the space before on null input if (spaceBefore == null) { if(_p.getPPr().isSetSpcBef()) { _p.getPPr().unsetSpcBef(); } return; } CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); if(spaceBefore >= 0) { spc.addNewSpcPct().setVal((int)(spaceBefore*1000)); } else { spc.addNewSpcPts().setVal((int)(-spaceBefore*100)); } pr.setSpcBef(spc); } @Override public Double getSpaceBefore(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetSpcBef()){ CTTextSpacing spc = props.getSpcBef(); if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 ); else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } @Override public void setSpaceAfter(Double spaceAfter){ if (spaceAfter == null && !_p.isSetPPr()) { return; } // unset the space before on null input if (spaceAfter == null) { if(_p.getPPr().isSetSpcAft()) { _p.getPPr().unsetSpcAft(); } return; } CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); if(spaceAfter >= 0) { spc.addNewSpcPct().setVal((int)(spaceAfter*1000)); } else { spc.addNewSpcPts().setVal((int)(-spaceAfter*100)); } pr.setSpcAft(spc); } @Override public Double getSpaceAfter(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetSpcAft()){ CTTextSpacing spc = props.getSpcAft(); if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 ); else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue(); } @Override public void setIndentLevel(int level){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); pr.setLvl(level); } @Override public int getIndentLevel() { CTTextParagraphProperties pr = _p.getPPr(); return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl(); } /** * Returns whether this paragraph has bullets */ public boolean isBullet() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetBuNone()) { setValue(false); return true; } if(props.isSetBuFont() || props.isSetBuChar()){ setValue(true); return true; } return false; } }; fetchParagraphProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } /** * * @param flag whether text in this paragraph has bullets */ public void setBullet(boolean flag) { if(isBullet() == flag) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); if(flag) { pr.addNewBuFont().setTypeface("Arial"); pr.addNewBuChar().setChar("\u2022"); } else { if (pr.isSetBuFont()) pr.unsetBuFont(); if (pr.isSetBuChar()) pr.unsetBuChar(); if (pr.isSetBuAutoNum()) pr.unsetBuAutoNum(); if (pr.isSetBuBlip()) pr.unsetBuBlip(); if (pr.isSetBuClr()) pr.unsetBuClr(); if (pr.isSetBuClrTx()) pr.unsetBuClrTx(); if (pr.isSetBuFont()) pr.unsetBuFont(); if (pr.isSetBuFontTx()) pr.unsetBuFontTx(); if (pr.isSetBuSzPct()) pr.unsetBuSzPct(); if (pr.isSetBuSzPts()) pr.unsetBuSzPts(); if (pr.isSetBuSzTx()) pr.unsetBuSzTx(); pr.addNewBuNone(); } } /** * Specifies that automatic numbered bullet points should be applied to this paragraph * * @param scheme type of auto-numbering * @param startAt the number that will start number for a given sequence of automatically numbered bullets (1-based). */ public void setBulletAutoNumber(AutoNumberingScheme scheme, int startAt) { if(startAt < 1) throw new IllegalArgumentException("Start Number must be greater or equal that 1") ; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum(); lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ooxmlId)); lst.setStartAt(startAt); } @Override public String toString(){ return "[" + getClass() + "]" + getText(); } /** * @return master style text paragraph properties, or null if * there are no master slides or the master slides do not contain a text paragraph */ /* package */ CTTextParagraphProperties getDefaultMasterStyle(){ CTPlaceholder ph = _shape.getCTPlaceholder(); String defaultStyleSelector; switch(ph == null ? -1 : ph.getType().intValue()) { case STPlaceholderType.INT_TITLE: case STPlaceholderType.INT_CTR_TITLE: defaultStyleSelector = "titleStyle"; break; case -1: // no placeholder means plain text box case STPlaceholderType.INT_FTR: case STPlaceholderType.INT_SLD_NUM: case STPlaceholderType.INT_DT: defaultStyleSelector = "otherStyle"; break; default: defaultStyleSelector = "bodyStyle"; break; } int level = getIndentLevel(); // wind up and find the root master sheet which must be slide master final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main"; final String nsDML = "http://schemas.openxmlformats.org/drawingml/2006/main"; XSLFSheet masterSheet = _shape.getSheet(); for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) { masterSheet = m; XmlObject xo = masterSheet.getXmlObject(); XmlCursor cur = xo.newCursor(); try { cur.push(); if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) || (cur.pop() && cur.toChild(nsPML, "notesStyle"))) { while (level >= 0) { cur.push(); if (cur.toChild(nsDML, "lvl" +(level+1)+ "pPr")) { return (CTTextParagraphProperties)cur.getObject(); } cur.pop(); level--; } } } finally { cur.dispose(); } } return null; } private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){ boolean ok = false; XSLFTextShape shape = getParentShape(); XSLFSheet sheet = shape.getSheet(); if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr()); if (ok) return true; ok = shape.fetchShapeProperty(visitor); if (ok) return true; CTPlaceholder ph = shape.getCTPlaceholder(); if(ph == null){ // if it is a plain text box then take defaults from presentation.xml @SuppressWarnings("resource") XMLSlideShow ppt = sheet.getSlideShow(); CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel()); if (themeProps != null) ok = visitor.fetch(themeProps); } if (ok) return true; // defaults for placeholders are defined in the slide master CTTextParagraphProperties defaultProps = getDefaultMasterStyle(); // TODO: determine master shape if(defaultProps != null) ok = visitor.fetch(defaultProps); if (ok) return true; return false; } void copy(XSLFTextParagraph other){ if (other == this) return; CTTextParagraph thisP = getXmlObject(); CTTextParagraph otherP = other.getXmlObject(); if (thisP.isSetPPr()) thisP.unsetPPr(); if (thisP.isSetEndParaRPr()) thisP.unsetEndParaRPr(); _runs.clear(); for (int i=thisP.sizeOfBrArray(); i>0; i--) { thisP.removeBr(i-1); } for (int i=thisP.sizeOfRArray(); i>0; i--) { thisP.removeR(i-1); } for (int i=thisP.sizeOfFldArray(); i>0; i--) { thisP.removeFld(i-1); } XmlCursor thisC = thisP.newCursor(); thisC.toEndToken(); XmlCursor otherC = otherP.newCursor(); otherC.copyXmlContents(thisC); otherC.dispose(); thisC.dispose(); List otherRs = other.getTextRuns(); int i=0; for(CTRegularTextRun rtr : thisP.getRArray()) { XSLFTextRun run = newTextRun(rtr); run.copy(otherRs.get(i++)); _runs.add(run); } // set properties again, in case we are based on a different // template TextAlign srcAlign = other.getTextAlign(); if(srcAlign != getTextAlign()){ setTextAlign(srcAlign); } boolean isBullet = other.isBullet(); if(isBullet != isBullet()){ setBullet(isBullet); if(isBullet) { String buFont = other.getBulletFont(); if(buFont != null && !buFont.equals(getBulletFont())){ setBulletFont(buFont); } String buChar = other.getBulletCharacter(); if(buChar != null && !buChar.equals(getBulletCharacter())){ setBulletCharacter(buChar); } PaintStyle buColor = other.getBulletFontColor(); if(buColor != null && !buColor.equals(getBulletFontColor())){ setBulletFontColor(buColor); } Double buSize = other.getBulletFontSize(); if(!doubleEquals(buSize, getBulletFontSize())){ setBulletFontSize(buSize); } } } Double leftMargin = other.getLeftMargin(); if (!doubleEquals(leftMargin, getLeftMargin())){ setLeftMargin(leftMargin); } Double indent = other.getIndent(); if (!doubleEquals(indent, getIndent())) { setIndent(indent); } Double spaceAfter = other.getSpaceAfter(); if (!doubleEquals(spaceAfter, getSpaceAfter())) { setSpaceAfter(spaceAfter); } Double spaceBefore = other.getSpaceBefore(); if (!doubleEquals(spaceBefore, getSpaceBefore())) { setSpaceBefore(spaceBefore); } Double lineSpacing = other.getLineSpacing(); if (!doubleEquals(lineSpacing, getLineSpacing())) { setLineSpacing(lineSpacing); } } private static boolean doubleEquals(Double d1, Double d2) { return (d1 == d2 || (d1 != null && d1.equals(d2))); } @Override public Double getDefaultFontSize() { CTTextCharacterProperties endPr = _p.getEndParaRPr(); if (endPr == null || !endPr.isSetSz()) { // inherit the font size from the master style CTTextParagraphProperties masterStyle = getDefaultMasterStyle(); if (masterStyle != null) { endPr = masterStyle.getDefRPr(); } } return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.); } @Override public String getDefaultFontFamily() { return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily()); } @Override public BulletStyle getBulletStyle() { if (!isBullet()) return null; return new BulletStyle(){ @Override public String getBulletCharacter() { return XSLFTextParagraph.this.getBulletCharacter(); } @Override public String getBulletFont() { return XSLFTextParagraph.this.getBulletFont(); } @Override public Double getBulletFontSize() { return XSLFTextParagraph.this.getBulletFontSize(); } @Override public PaintStyle getBulletFontColor() { return XSLFTextParagraph.this.getBulletFontColor(); } @Override public void setBulletFontColor(Color color) { setBulletFontColor(DrawPaint.createSolidPaint(color)); } @Override public void setBulletFontColor(PaintStyle color) { XSLFTextParagraph.this.setBulletFontColor(color); } @Override public AutoNumberingScheme getAutoNumberingScheme() { return XSLFTextParagraph.this.getAutoNumberingScheme(); } @Override public Integer getAutoNumberingStartAt() { return XSLFTextParagraph.this.getAutoNumberingStartAt(); } }; } @Override public void setBulletStyle(Object... styles) { if (styles.length == 0) { setBullet(false); } else { setBullet(true); for (Object ostyle : styles) { if (ostyle instanceof Number) { setBulletFontSize(((Number)ostyle).doubleValue()); } else if (ostyle instanceof Color) { setBulletFontColor((Color)ostyle); } else if (ostyle instanceof Character) { setBulletCharacter(ostyle.toString()); } else if (ostyle instanceof String) { setBulletFont((String)ostyle); } else if (ostyle instanceof AutoNumberingScheme) { setBulletAutoNumber((AutoNumberingScheme)ostyle, 0); } } } } /** * Helper method for appending text and keeping paragraph and character properties. * The character properties are moved to the end paragraph marker */ /* package */ void clearButKeepProperties() { CTTextParagraph thisP = getXmlObject(); for (int i=thisP.sizeOfBrArray(); i>0; i--) { thisP.removeBr(i-1); } for (int i=thisP.sizeOfFldArray(); i>0; i--) { thisP.removeFld(i-1); } if (!_runs.isEmpty()) { int size = _runs.size(); XSLFTextRun lastRun = _runs.get(size-1); CTTextCharacterProperties cpOther = lastRun.getRPr(false); if (cpOther != null) { if (thisP.isSetEndParaRPr()) { thisP.unsetEndParaRPr(); } CTTextCharacterProperties cp = thisP.addNewEndParaRPr(); cp.set(cpOther); } for (int i=size; i>0; i--) { thisP.removeR(i-1); } _runs.clear(); } } @Override public boolean isHeaderOrFooter() { CTPlaceholder ph = _shape.getCTPlaceholder(); int phId = (ph == null ? -1 : ph.getType().intValue()); switch (phId) { case STPlaceholderType.INT_SLD_NUM: case STPlaceholderType.INT_DT: case STPlaceholderType.INT_FTR: case STPlaceholderType.INT_HDR: return true; default: return false; } } /** * Helper method to allow subclasses to provide their own text run * * @param r the xml reference * * @return a new text paragraph * * @since POI 3.15-beta2 */ protected XSLFTextRun newTextRun(CTRegularTextRun r) { return new XSLFTextRun(r, this); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy