You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. * ====================================================================
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with
  5. * this work for additional information regarding copyright ownership.
  6. * The ASF licenses this file to You under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. * ====================================================================
  18. */
  19. package org.apache.poi.xslf.usermodel;
  20. import java.awt.Graphics2D;
  21. import java.awt.geom.Rectangle2D;
  22. import java.util.ArrayList;
  23. import java.util.Iterator;
  24. import java.util.List;
  25. import org.apache.poi.POIXMLException;
  26. import org.apache.poi.sl.draw.DrawFactory;
  27. import org.apache.poi.sl.draw.DrawTextShape;
  28. import org.apache.poi.sl.usermodel.Insets2D;
  29. import org.apache.poi.sl.usermodel.Placeholder;
  30. import org.apache.poi.sl.usermodel.TextShape;
  31. import org.apache.poi.sl.usermodel.VerticalAlignment;
  32. import org.apache.poi.util.Beta;
  33. import org.apache.poi.util.Units;
  34. import org.apache.poi.xslf.model.PropertyFetcher;
  35. import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
  36. import org.apache.xmlbeans.XmlObject;
  37. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
  38. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
  39. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
  40. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
  41. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
  42. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
  43. import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
  44. import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
  45. import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
  46. import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
  47. /**
  48. * Represents a shape that can hold text.
  49. */
  50. @Beta
  51. public abstract class XSLFTextShape extends XSLFSimpleShape
  52. implements TextShape<XSLFShape,XSLFTextParagraph> {
  53. private final List<XSLFTextParagraph> _paragraphs;
  54. /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
  55. super(shape, sheet);
  56. _paragraphs = new ArrayList<XSLFTextParagraph>();
  57. CTTextBody txBody = getTextBody(false);
  58. if (txBody != null) {
  59. for (CTTextParagraph p : txBody.getPArray()) {
  60. _paragraphs.add(newTextParagraph(p));
  61. }
  62. }
  63. }
  64. @Override
  65. public Iterator<XSLFTextParagraph> iterator(){
  66. return getTextParagraphs().iterator();
  67. }
  68. @Override
  69. public String getText() {
  70. StringBuilder out = new StringBuilder();
  71. for (XSLFTextParagraph p : _paragraphs) {
  72. if (out.length() > 0) {
  73. out.append('\n');
  74. }
  75. out.append(p.getText());
  76. }
  77. return out.toString();
  78. }
  79. /**
  80. * unset text from this shape
  81. */
  82. public void clearText(){
  83. _paragraphs.clear();
  84. CTTextBody txBody = getTextBody(true);
  85. txBody.setPArray(null); // remove any existing paragraphs
  86. }
  87. @Override
  88. public XSLFTextRun setText(String text) {
  89. // calling clearText or setting to a new Array leads to a XmlValueDisconnectedException
  90. if (!_paragraphs.isEmpty()) {
  91. CTTextBody txBody = getTextBody(false);
  92. int cntPs = txBody.sizeOfPArray();
  93. for (int i = cntPs; i > 1; i--) {
  94. txBody.removeP(i-1);
  95. _paragraphs.remove(i-1);
  96. }
  97. _paragraphs.get(0).clearButKeepProperties();
  98. }
  99. return appendText(text, false);
  100. }
  101. @Override
  102. public XSLFTextRun appendText(String text, boolean newParagraph) {
  103. if (text == null) {
  104. return null;
  105. }
  106. // copy properties from last paragraph / textrun or paragraph end marker
  107. CTTextParagraphProperties otherPPr = null;
  108. CTTextCharacterProperties otherRPr = null;
  109. boolean firstPara;
  110. XSLFTextParagraph para;
  111. if (_paragraphs.isEmpty()) {
  112. firstPara = false;
  113. para = null;
  114. } else {
  115. firstPara = !newParagraph;
  116. para = _paragraphs.get(_paragraphs.size()-1);
  117. CTTextParagraph ctp = para.getXmlObject();
  118. otherPPr = ctp.getPPr();
  119. List<XSLFTextRun> runs = para.getTextRuns();
  120. if (!runs.isEmpty()) {
  121. XSLFTextRun r0 = runs.get(runs.size()-1);
  122. otherRPr = r0.getRPr(false);
  123. if (otherRPr == null) {
  124. otherRPr = ctp.getEndParaRPr();
  125. }
  126. }
  127. // don't copy endParaRPr to the run in case there aren't any other runs
  128. // this is the case when setText() was called initially
  129. // otherwise the master style will be overridden/ignored
  130. }
  131. XSLFTextRun run = null;
  132. for (String lineTxt : text.split("\\r\\n?|\\n")) {
  133. if (!firstPara) {
  134. if (para != null) {
  135. CTTextParagraph ctp = para.getXmlObject();
  136. CTTextCharacterProperties unexpectedRPr = ctp.getEndParaRPr();
  137. if (unexpectedRPr != null && unexpectedRPr != otherRPr) {
  138. ctp.unsetEndParaRPr();
  139. }
  140. }
  141. para = addNewTextParagraph();
  142. if (otherPPr != null) {
  143. para.getXmlObject().setPPr(otherPPr);
  144. }
  145. }
  146. boolean firstRun = true;
  147. for (String runText : lineTxt.split("[\u000b]")) {
  148. if (!firstRun) {
  149. para.addLineBreak();
  150. }
  151. run = para.addNewTextRun();
  152. run.setText(runText);
  153. if (otherRPr != null) {
  154. run.getRPr(true).set(otherRPr);
  155. }
  156. firstRun = false;
  157. }
  158. firstPara = false;
  159. }
  160. assert(run != null);
  161. return run;
  162. }
  163. @Override
  164. public List<XSLFTextParagraph> getTextParagraphs() {
  165. return _paragraphs;
  166. }
  167. /**
  168. * add a new paragraph run to this shape
  169. *
  170. * @return created paragraph run
  171. */
  172. public XSLFTextParagraph addNewTextParagraph() {
  173. CTTextBody txBody = getTextBody(false);
  174. CTTextParagraph p;
  175. if (txBody == null) {
  176. txBody = getTextBody(true);
  177. p = txBody.getPArray(0);
  178. p.removeR(0);
  179. } else {
  180. p = txBody.addNewP();
  181. }
  182. XSLFTextParagraph paragraph = newTextParagraph(p);
  183. _paragraphs.add(paragraph);
  184. return paragraph;
  185. }
  186. @Override
  187. public void setVerticalAlignment(VerticalAlignment anchor){
  188. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  189. if (bodyPr != null) {
  190. if(anchor == null) {
  191. if(bodyPr.isSetAnchor()) {
  192. bodyPr.unsetAnchor();
  193. }
  194. } else {
  195. bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
  196. }
  197. }
  198. }
  199. @Override
  200. public VerticalAlignment getVerticalAlignment(){
  201. PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){
  202. @Override
  203. public boolean fetch(CTTextBodyProperties props){
  204. if(props.isSetAnchor()){
  205. int val = props.getAnchor().intValue();
  206. setValue(VerticalAlignment.values()[val - 1]);
  207. return true;
  208. }
  209. return false;
  210. }
  211. };
  212. fetchShapeProperty(fetcher);
  213. return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
  214. }
  215. @Override
  216. public void setHorizontalCentered(Boolean isCentered){
  217. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  218. if (bodyPr != null) {
  219. if (isCentered == null) {
  220. if (bodyPr.isSetAnchorCtr()) {
  221. bodyPr.unsetAnchorCtr();
  222. }
  223. } else {
  224. bodyPr.setAnchorCtr(isCentered);
  225. }
  226. }
  227. }
  228. @Override
  229. public boolean isHorizontalCentered(){
  230. PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
  231. @Override
  232. public boolean fetch(CTTextBodyProperties props){
  233. if(props.isSetAnchorCtr()){
  234. setValue(props.getAnchorCtr());
  235. return true;
  236. }
  237. return false;
  238. }
  239. };
  240. fetchShapeProperty(fetcher);
  241. return fetcher.getValue() == null ? false : fetcher.getValue();
  242. }
  243. @Override
  244. public void setTextDirection(TextDirection orientation){
  245. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  246. if (bodyPr != null) {
  247. if(orientation == null) {
  248. if(bodyPr.isSetVert()) {
  249. bodyPr.unsetVert();
  250. }
  251. } else {
  252. bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
  253. }
  254. }
  255. }
  256. @Override
  257. public TextDirection getTextDirection(){
  258. CTTextBodyProperties bodyPr = getTextBodyPr();
  259. if (bodyPr != null) {
  260. STTextVerticalType.Enum val = bodyPr.getVert();
  261. if(val != null) {
  262. switch (val.intValue()) {
  263. default:
  264. case STTextVerticalType.INT_HORZ:
  265. return TextDirection.HORIZONTAL;
  266. case STTextVerticalType.INT_EA_VERT:
  267. case STTextVerticalType.INT_MONGOLIAN_VERT:
  268. case STTextVerticalType.INT_VERT:
  269. return TextDirection.VERTICAL;
  270. case STTextVerticalType.INT_VERT_270:
  271. return TextDirection.VERTICAL_270;
  272. case STTextVerticalType.INT_WORD_ART_VERT_RTL:
  273. case STTextVerticalType.INT_WORD_ART_VERT:
  274. return TextDirection.STACKED;
  275. }
  276. }
  277. }
  278. return TextDirection.HORIZONTAL;
  279. }
  280. @Override
  281. public Double getTextRotation() {
  282. CTTextBodyProperties bodyPr = getTextBodyPr();
  283. if (bodyPr != null && bodyPr.isSetRot()) {
  284. return bodyPr.getRot() / 60000.;
  285. }
  286. return null;
  287. }
  288. @Override
  289. public void setTextRotation(Double rotation) {
  290. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  291. if (bodyPr != null) {
  292. bodyPr.setRot((int)(rotation * 60000.));
  293. }
  294. }
  295. /**
  296. * Returns the distance (in points) between the bottom of the text frame
  297. * and the bottom of the inscribed rectangle of the shape that contains the text.
  298. *
  299. * @return the bottom inset in points
  300. */
  301. public double getBottomInset(){
  302. PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
  303. @Override
  304. public boolean fetch(CTTextBodyProperties props){
  305. if(props.isSetBIns()){
  306. double val = Units.toPoints(props.getBIns());
  307. setValue(val);
  308. return true;
  309. }
  310. return false;
  311. }
  312. };
  313. fetchShapeProperty(fetcher);
  314. // If this attribute is omitted, then a value of 0.05 inches is implied
  315. return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
  316. }
  317. /**
  318. * Returns the distance (in points) between the left edge of the text frame
  319. * and the left edge of the inscribed rectangle of the shape that contains
  320. * the text.
  321. *
  322. * @return the left inset in points
  323. */
  324. public double getLeftInset(){
  325. PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
  326. @Override
  327. public boolean fetch(CTTextBodyProperties props){
  328. if(props.isSetLIns()){
  329. double val = Units.toPoints(props.getLIns());
  330. setValue(val);
  331. return true;
  332. }
  333. return false;
  334. }
  335. };
  336. fetchShapeProperty(fetcher);
  337. // If this attribute is omitted, then a value of 0.1 inches is implied
  338. return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
  339. }
  340. /**
  341. * Returns the distance (in points) between the right edge of the
  342. * text frame and the right edge of the inscribed rectangle of the shape
  343. * that contains the text.
  344. *
  345. * @return the right inset in points
  346. */
  347. public double getRightInset(){
  348. PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
  349. @Override
  350. public boolean fetch(CTTextBodyProperties props){
  351. if(props.isSetRIns()){
  352. double val = Units.toPoints(props.getRIns());
  353. setValue(val);
  354. return true;
  355. }
  356. return false;
  357. }
  358. };
  359. fetchShapeProperty(fetcher);
  360. // If this attribute is omitted, then a value of 0.1 inches is implied
  361. return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
  362. }
  363. /**
  364. * Returns the distance (in points) between the top of the text frame
  365. * and the top of the inscribed rectangle of the shape that contains the text.
  366. *
  367. * @return the top inset in points
  368. */
  369. public double getTopInset(){
  370. PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
  371. @Override
  372. public boolean fetch(CTTextBodyProperties props){
  373. if(props.isSetTIns()){
  374. double val = Units.toPoints(props.getTIns());
  375. setValue(val);
  376. return true;
  377. }
  378. return false;
  379. }
  380. };
  381. fetchShapeProperty(fetcher);
  382. // If this attribute is omitted, then a value of 0.05 inches is implied
  383. return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
  384. }
  385. /**
  386. * Sets the bottom margin.
  387. * @see #getBottomInset()
  388. *
  389. * @param margin the bottom margin
  390. */
  391. public void setBottomInset(double margin){
  392. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  393. if (bodyPr != null) {
  394. if(margin == -1) {
  395. bodyPr.unsetBIns();
  396. } else {
  397. bodyPr.setBIns(Units.toEMU(margin));
  398. }
  399. }
  400. }
  401. /**
  402. * Sets the left margin.
  403. * @see #getLeftInset()
  404. *
  405. * @param margin the left margin
  406. */
  407. public void setLeftInset(double margin){
  408. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  409. if (bodyPr != null) {
  410. if(margin == -1) {
  411. bodyPr.unsetLIns();
  412. } else {
  413. bodyPr.setLIns(Units.toEMU(margin));
  414. }
  415. }
  416. }
  417. /**
  418. * Sets the right margin.
  419. * @see #getRightInset()
  420. *
  421. * @param margin the right margin
  422. */
  423. public void setRightInset(double margin){
  424. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  425. if (bodyPr != null) {
  426. if(margin == -1) {
  427. bodyPr.unsetRIns();
  428. } else {
  429. bodyPr.setRIns(Units.toEMU(margin));
  430. }
  431. }
  432. }
  433. /**
  434. * Sets the top margin.
  435. * @see #getTopInset()
  436. *
  437. * @param margin the top margin
  438. */
  439. public void setTopInset(double margin){
  440. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  441. if (bodyPr != null) {
  442. if(margin == -1) {
  443. bodyPr.unsetTIns();
  444. } else {
  445. bodyPr.setTIns(Units.toEMU(margin));
  446. }
  447. }
  448. }
  449. @Override
  450. public Insets2D getInsets() {
  451. Insets2D insets = new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset());
  452. return insets;
  453. }
  454. @Override
  455. public void setInsets(Insets2D insets) {
  456. setTopInset(insets.top);
  457. setLeftInset(insets.left);
  458. setBottomInset(insets.bottom);
  459. setRightInset(insets.right);
  460. }
  461. @Override
  462. public boolean getWordWrap(){
  463. PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
  464. @Override
  465. public boolean fetch(CTTextBodyProperties props){
  466. if(props.isSetWrap()){
  467. setValue(props.getWrap() == STTextWrappingType.SQUARE);
  468. return true;
  469. }
  470. return false;
  471. }
  472. };
  473. fetchShapeProperty(fetcher);
  474. return fetcher.getValue() == null ? true : fetcher.getValue();
  475. }
  476. @Override
  477. public void setWordWrap(boolean wrap){
  478. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  479. if (bodyPr != null) {
  480. bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
  481. }
  482. }
  483. /**
  484. *
  485. * Specifies that a shape should be auto-fit to fully contain the text described within it.
  486. * Auto-fitting is when text within a shape is scaled in order to contain all the text inside
  487. *
  488. * @param value type of autofit
  489. */
  490. public void setTextAutofit(TextAutofit value){
  491. CTTextBodyProperties bodyPr = getTextBodyPr(true);
  492. if (bodyPr != null) {
  493. if(bodyPr.isSetSpAutoFit()) {
  494. bodyPr.unsetSpAutoFit();
  495. }
  496. if(bodyPr.isSetNoAutofit()) {
  497. bodyPr.unsetNoAutofit();
  498. }
  499. if(bodyPr.isSetNormAutofit()) {
  500. bodyPr.unsetNormAutofit();
  501. }
  502. switch(value){
  503. case NONE: bodyPr.addNewNoAutofit(); break;
  504. case NORMAL: bodyPr.addNewNormAutofit(); break;
  505. case SHAPE: bodyPr.addNewSpAutoFit(); break;
  506. }
  507. }
  508. }
  509. /**
  510. *
  511. * @return type of autofit
  512. */
  513. public TextAutofit getTextAutofit(){
  514. CTTextBodyProperties bodyPr = getTextBodyPr();
  515. if (bodyPr != null) {
  516. if(bodyPr.isSetNoAutofit()) {
  517. return TextAutofit.NONE;
  518. } else if (bodyPr.isSetNormAutofit()) {
  519. return TextAutofit.NORMAL;
  520. } else if (bodyPr.isSetSpAutoFit()) {
  521. return TextAutofit.SHAPE;
  522. }
  523. }
  524. return TextAutofit.NORMAL;
  525. }
  526. protected CTTextBodyProperties getTextBodyPr(){
  527. return getTextBodyPr(false);
  528. }
  529. protected CTTextBodyProperties getTextBodyPr(boolean create) {
  530. CTTextBody textBody = getTextBody(create);
  531. if (textBody == null) {
  532. return null;
  533. }
  534. CTTextBodyProperties textBodyPr = textBody.getBodyPr();
  535. if (textBodyPr == null && create) {
  536. textBodyPr = textBody.addNewBodyPr();
  537. }
  538. return textBodyPr;
  539. }
  540. protected abstract CTTextBody getTextBody(boolean create);
  541. @Override
  542. public void setPlaceholder(Placeholder placeholder) {
  543. super.setPlaceholder(placeholder);
  544. }
  545. public Placeholder getTextType(){
  546. CTPlaceholder ph = getCTPlaceholder();
  547. if (ph == null) {
  548. return null;
  549. }
  550. int val = ph.getType().intValue();
  551. return Placeholder.lookupOoxml(val);
  552. }
  553. @Override
  554. public double getTextHeight(){
  555. return getTextHeight(null);
  556. }
  557. @Override
  558. public double getTextHeight(Graphics2D graphics){
  559. DrawFactory drawFact = DrawFactory.getInstance(graphics);
  560. DrawTextShape dts = drawFact.getDrawable(this);
  561. return dts.getTextHeight(graphics);
  562. }
  563. @Override
  564. public Rectangle2D resizeToFitText(){
  565. return resizeToFitText(null);
  566. }
  567. @Override
  568. public Rectangle2D resizeToFitText(Graphics2D graphics) {
  569. Rectangle2D anchor = getAnchor();
  570. if(anchor.getWidth() == 0.) {
  571. throw new POIXMLException("Anchor of the shape was not set.");
  572. }
  573. double height = getTextHeight(graphics);
  574. height += 1; // add a pixel to compensate rounding errors
  575. Insets2D insets = getInsets();
  576. anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height+insets.top+insets.bottom);
  577. setAnchor(anchor);
  578. return anchor;
  579. }
  580. @Override
  581. void copy(XSLFShape other){
  582. super.copy(other);
  583. XSLFTextShape otherTS = (XSLFTextShape)other;
  584. CTTextBody otherTB = otherTS.getTextBody(false);
  585. CTTextBody thisTB = getTextBody(true);
  586. if (otherTB == null) {
  587. return;
  588. }
  589. thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy());
  590. if (thisTB.isSetLstStyle()) {
  591. thisTB.unsetLstStyle();
  592. }
  593. if (otherTB.isSetLstStyle()) {
  594. thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy());
  595. }
  596. boolean srcWordWrap = otherTS.getWordWrap();
  597. if(srcWordWrap != getWordWrap()){
  598. setWordWrap(srcWordWrap);
  599. }
  600. double leftInset = otherTS.getLeftInset();
  601. if(leftInset != getLeftInset()) {
  602. setLeftInset(leftInset);
  603. }
  604. double rightInset = otherTS.getRightInset();
  605. if(rightInset != getRightInset()) {
  606. setRightInset(rightInset);
  607. }
  608. double topInset = otherTS.getTopInset();
  609. if(topInset != getTopInset()) {
  610. setTopInset(topInset);
  611. }
  612. double bottomInset = otherTS.getBottomInset();
  613. if(bottomInset != getBottomInset()) {
  614. setBottomInset(bottomInset);
  615. }
  616. VerticalAlignment vAlign = otherTS.getVerticalAlignment();
  617. if(vAlign != getVerticalAlignment()) {
  618. setVerticalAlignment(vAlign);
  619. }
  620. clearText();
  621. for (XSLFTextParagraph srcP : otherTS.getTextParagraphs()) {
  622. XSLFTextParagraph tgtP = addNewTextParagraph();
  623. tgtP.copy(srcP);
  624. }
  625. }
  626. @Override
  627. public void setTextPlaceholder(TextPlaceholder placeholder) {
  628. switch (placeholder) {
  629. default:
  630. case NOTES:
  631. case HALF_BODY:
  632. case QUARTER_BODY:
  633. case BODY:
  634. setPlaceholder(Placeholder.BODY);
  635. break;
  636. case TITLE:
  637. setPlaceholder(Placeholder.TITLE);
  638. break;
  639. case CENTER_BODY:
  640. setPlaceholder(Placeholder.BODY);
  641. setHorizontalCentered(true);
  642. break;
  643. case CENTER_TITLE:
  644. setPlaceholder(Placeholder.CENTERED_TITLE);
  645. break;
  646. case OTHER:
  647. setPlaceholder(Placeholder.CONTENT);
  648. break;
  649. }
  650. }
  651. @Override
  652. public TextPlaceholder getTextPlaceholder() {
  653. Placeholder ph = getTextType();
  654. if (ph == null) {
  655. return TextPlaceholder.BODY;
  656. }
  657. switch (ph) {
  658. case BODY: return TextPlaceholder.BODY;
  659. case TITLE: return TextPlaceholder.TITLE;
  660. case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE;
  661. default:
  662. case CONTENT: return TextPlaceholder.OTHER;
  663. }
  664. }
  665. /**
  666. * Helper method to allow subclasses to provide their own text paragraph
  667. *
  668. * @param p the xml reference
  669. *
  670. * @return a new text paragraph
  671. *
  672. * @since POI 3.15-beta2
  673. */
  674. protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) {
  675. return new XSLFTextParagraph(p, this);
  676. }
  677. }